diff --git a/.golangci.yml b/.golangci.yml index 9972a903e..2f8d0cfa9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -51,10 +51,14 @@ issues: - text: "G306:" linters: - gosec - # Exlude tests from long line linter + # Exclude tests from long line linter - linters: - lll path: _test\.go + # Exclude tests from duplicate linter + - linters: + - dupl + path: _test\.go # always show all issues rather than only showing 50 at a time max-issues-per-linter: 0 # always show all issues of a type rather than showing 3 diff --git a/pkg/controllers/routing/bgp_policies_test.go b/pkg/controllers/routing/bgp_policies_test.go index c58dab1a2..5da30c47c 100644 --- a/pkg/controllers/routing/bgp_policies_test.go +++ b/pkg/controllers/routing/bgp_policies_test.go @@ -21,6 +21,7 @@ type PolicyTestCase struct { nrc *NetworkRoutingController existingNodes []*v1core.Node existingServices []*v1core.Service + existingEndpoints []*v1core.Endpoints podDefinedSet *gobgpapi.DefinedSet clusterIPDefinedSet *gobgpapi.DefinedSet externalPeerDefinedSet *gobgpapi.DefinedSet @@ -75,12 +76,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.1.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.1.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -205,12 +226,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: "ClusterIP", - ClusterIP: "10.11.0.1", - ExternalIPs: []string{"1.11.1.1"}, + Type: "ClusterIP", + ClusterIP: "10.11.0.1", + ExternalIPs: []string{"1.11.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -428,12 +469,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.12.0.1", - ExternalIPs: []string{"1.12.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.12.0.1", + ExternalIPs: []string{"1.12.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -613,12 +674,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.13.0.1", - ExternalIPs: []string{"1.13.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.13.0.1", + ExternalIPs: []string{"1.13.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -783,12 +864,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.14.0.1", - ExternalIPs: []string{"1.14.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.14.0.1", + ExternalIPs: []string{"1.14.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -973,12 +1074,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.15.0.1", - ExternalIPs: []string{"1.15.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.15.0.1", + ExternalIPs: []string{"1.15.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -1164,12 +1285,32 @@ func Test_AddPolicies(t *testing.T) { []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.16.0.1", - ExternalIPs: []string{"1.16.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.16.0.1", + ExternalIPs: []string{"1.16.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -1309,7 +1450,11 @@ func Test_AddPolicies(t *testing.T) { } if err := createServices(testcase.nrc.clientset, testcase.existingServices); err != nil { - t.Errorf("failed to create existing nodes: %v", err) + t.Errorf("failed to create existing services: %v", err) + } + + if err := createEndpoints(testcase.nrc.clientset, testcase.existingEndpoints); err != nil { + t.Errorf("failed to create existing endpoints: %v", err) } err := testcase.nrc.startBgpServer(false) diff --git a/pkg/controllers/routing/ecmp_vip_test.go b/pkg/controllers/routing/ecmp_vip_test.go index 7a10e1810..e53da6e5b 100644 --- a/pkg/controllers/routing/ecmp_vip_test.go +++ b/pkg/controllers/routing/ecmp_vip_test.go @@ -2,7 +2,9 @@ package routing import ( "context" + "net" "testing" + "time" v1core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -22,98 +24,67 @@ func Equal(a, b []string) bool { return true } +var ( + testlocalExtTrafPol = v1core.ServiceExternalTrafficPolicyLocal + testClusterExtTrafPol = v1core.ServiceExternalTrafficPolicyCluster + testLocalIntTrafPol = v1core.ServiceInternalTrafficPolicyLocal + testClusterIntTrafPol = v1core.ServiceInternalTrafficPolicyCluster + testNodeIPv4 = "10.1.0.1" + testNodeIPv6 = "2001:db8:42:2::1" +) + type ServiceAdvertisedIPs struct { - service *v1core.Service - advertisedIPs []string - withdrawnIPs []string - annotations map[string]string + service *v1core.Service + endpoints *v1core.Endpoints + internalTrafficPolicy *v1core.ServiceInternalTrafficPolicyType + externalTrafficPolicy *v1core.ServiceExternalTrafficPolicyType + advertisedIPs []string + withdrawnIPs []string + annotations map[string]string } func Test_getVIPsForService(t *testing.T) { - services := map[string]*v1core.Service{ - "cluster": { - ObjectMeta: metav1.ObjectMeta{ - Name: "svc-cluster", - }, - Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - }, - }, - "external": { - ObjectMeta: metav1.ObjectMeta{ - Name: "svc-external", - }, - Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, - }, - }, - "nodeport": { - ObjectMeta: metav1.ObjectMeta{ - Name: "svc-nodeport", - }, - Spec: v1core.ServiceSpec{ - Type: NodePortST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, - }, - }, - "loadbalancer": { - ObjectMeta: metav1.ObjectMeta{ - Name: "svc-loadbalancer", - }, - Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, - }, - Status: v1core.ServiceStatus{ - LoadBalancer: v1core.LoadBalancerStatus{ - Ingress: []v1core.LoadBalancerIngress{ - { - IP: "10.0.255.1", - }, - { - IP: "10.0.255.2", - }, - }, - }, - }, - }, - } - tests := []struct { - name string - // cluster, external, loadbalancer - advertiseSettings [3]bool + name string + nrc *NetworkRoutingController serviceAdvertisedIPs []*ServiceAdvertisedIPs }{ { - name: "advertise all IPs", - advertiseSettings: [3]bool{true, true, true}, + name: "advertise all IPs", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1"}, withdrawnIPs: []string{}, annotations: nil, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, withdrawnIPs: []string{}, annotations: nil, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, withdrawnIPs: []string{}, annotations: nil, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, withdrawnIPs: []string{}, annotations: nil, @@ -121,29 +92,41 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - name: "do not advertise any IPs", - advertiseSettings: [3]bool{false, false, false}, + name: "do not advertise any IPs", + nrc: &NetworkRoutingController{ + advertiseClusterIP: false, + advertiseExternalIP: false, + advertiseLoadBalancerIP: false, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1"}, annotations: nil, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: nil, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: nil, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, annotations: nil, @@ -151,29 +134,41 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - name: "advertise cluster IPs", - advertiseSettings: [3]bool{true, false, false}, + name: "advertise cluster IPs", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: false, + advertiseLoadBalancerIP: false, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1"}, withdrawnIPs: []string{}, annotations: nil, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1"}, withdrawnIPs: []string{"1.1.1.1"}, annotations: nil, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1"}, withdrawnIPs: []string{"1.1.1.1"}, annotations: nil, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1"}, withdrawnIPs: []string{"1.1.1.1", "10.0.255.1", "10.0.255.2"}, annotations: nil, @@ -181,29 +176,41 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - name: "advertise external IPs", - advertiseSettings: [3]bool{false, true, false}, + name: "advertise external IPs", + nrc: &NetworkRoutingController{ + advertiseClusterIP: false, + advertiseExternalIP: true, + advertiseLoadBalancerIP: false, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1"}, annotations: nil, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"1.1.1.1"}, withdrawnIPs: []string{"10.0.0.1"}, annotations: nil, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"1.1.1.1"}, withdrawnIPs: []string{"10.0.0.1"}, annotations: nil, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"1.1.1.1"}, withdrawnIPs: []string{"10.0.0.1", "10.0.255.1", "10.0.255.2"}, annotations: nil, @@ -211,29 +218,41 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - name: "advertise loadbalancer IPs", - advertiseSettings: [3]bool{false, false, true}, + name: "advertise loadbalancer IPs", + nrc: &NetworkRoutingController{ + advertiseClusterIP: false, + advertiseExternalIP: false, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1"}, annotations: nil, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: nil, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: nil, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.255.1", "10.0.255.2"}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: nil, @@ -241,11 +260,20 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - name: "opt in to advertise all IPs via annotations", - advertiseSettings: [3]bool{false, false, false}, + name: "opt in to advertise all IPs via annotations", + nrc: &NetworkRoutingController{ + advertiseClusterIP: false, + advertiseExternalIP: false, + advertiseLoadBalancerIP: false, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1"}, withdrawnIPs: []string{}, annotations: map[string]string{ @@ -255,7 +283,8 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, withdrawnIPs: []string{}, annotations: map[string]string{ @@ -265,7 +294,8 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, withdrawnIPs: []string{}, annotations: map[string]string{ @@ -275,7 +305,8 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, withdrawnIPs: []string{}, annotations: map[string]string{ @@ -286,7 +317,8 @@ func Test_getVIPsForService(t *testing.T) { }, { // Special case to test svcAdvertiseLoadBalancerAnnotation vs legacy svcSkipLbIpsAnnotation - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, withdrawnIPs: []string{"10.0.255.1", "10.0.255.2"}, annotations: map[string]string{ @@ -299,11 +331,20 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - name: "opt out to advertise any IPs via annotations", - advertiseSettings: [3]bool{true, true, true}, + name: "opt out to advertise any IPs via annotations", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ { - service: services["cluster"], + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1"}, annotations: map[string]string{ @@ -313,7 +354,8 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - service: services["external"], + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: map[string]string{ @@ -323,7 +365,8 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - service: services["nodeport"], + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, annotations: map[string]string{ @@ -333,7 +376,8 @@ func Test_getVIPsForService(t *testing.T) { }, }, { - service: services["loadbalancer"], + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), advertisedIPs: []string{}, withdrawnIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, annotations: map[string]string{ @@ -344,23 +388,520 @@ func Test_getVIPsForService(t *testing.T) { }, }, }, + { + name: "check service local annotation with local IPv4 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + }, + }, + { + name: "check service local annotation with local IPv6 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv6), + nodeIPv6Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv6)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getExternalSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getNodePortSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, + withdrawnIPs: []string{}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + }, + }, + { + name: "check local external traffic policy with local IPv4 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getExternalSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getNodePortSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv4EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + }, + }, + { + name: "check local external traffic policy with local IPv6 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv6), + nodeIPv6Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv6)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getExternalSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getNodePortSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getLoadBalancerSvc(), + endpoints: getContainsLocalIPv6EPs(), + advertisedIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + }, + }, + { + name: "check service local annotation WITHOUT local IPv4 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv6Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv6)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getExternalSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getNodePortSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getLoadBalancerSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + }, + }, + { + name: "check service local annotation WITHOUT local IPv6 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv6), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getExternalSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getNodePortSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1", "1.1.1.1"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + { + service: getLoadBalancerSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1", "1.1.1.1", "10.0.255.1", "10.0.255.2"}, + annotations: map[string]string{ + svcLocalAnnotation: "true", + }, + }, + }, + }, + { + name: "check local external traffic policy WITHOUT local IPv4 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getExternalSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{"1.1.1.1"}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getNodePortSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{"1.1.1.1"}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getLoadBalancerSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{"1.1.1.1", "10.0.255.1", "10.0.255.2"}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + }, + }, + { + name: "check local external traffic policy WITHOUT local IPv6 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv6), + nodeIPv6Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv6)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getExternalSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{"1.1.1.1"}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getNodePortSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{"1.1.1.1"}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + { + service: getLoadBalancerSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"10.0.0.1"}, + withdrawnIPs: []string{"1.1.1.1", "10.0.255.1", "10.0.255.2"}, + annotations: nil, + externalTrafficPolicy: &testlocalExtTrafPol, + }, + }, + }, + { + name: "check local internal traffic policy WITHOUT local IPv4 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + { + service: getExternalSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"1.1.1.1"}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + { + service: getNodePortSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"1.1.1.1"}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + { + service: getLoadBalancerSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"1.1.1.1", "10.0.255.1", "10.0.255.2"}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + }, + }, + { + name: "check local internal traffic policy WITHOUT local IPv6 endpoints", + nrc: &NetworkRoutingController{ + advertiseClusterIP: true, + advertiseExternalIP: true, + advertiseLoadBalancerIP: true, + primaryIP: net.ParseIP(testNodeIPv6), + nodeIPv6Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv6)}, + }, + }, + serviceAdvertisedIPs: []*ServiceAdvertisedIPs{ + { + service: getClusterSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + { + service: getExternalSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"1.1.1.1"}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + { + service: getNodePortSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"1.1.1.1"}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + { + service: getLoadBalancerSvc(), + endpoints: getNoLocalAddressesEPs(), + advertisedIPs: []string{"1.1.1.1", "10.0.255.1", "10.0.255.2"}, + withdrawnIPs: []string{"10.0.0.1"}, + annotations: nil, + internalTrafficPolicy: &testLocalIntTrafPol, + }, + }, + }, } for _, test := range tests { - nrc := NetworkRoutingController{} t.Run(test.name, func(t *testing.T) { - nrc.advertiseClusterIP = test.advertiseSettings[0] - nrc.advertiseExternalIP = test.advertiseSettings[1] - nrc.advertiseLoadBalancerIP = test.advertiseSettings[2] - for _, serviceAdvertisedIP := range test.serviceAdvertisedIPs { + endpoints := serviceAdvertisedIP.endpoints clientset := fake.NewSimpleClientset() + startInformersForRoutes(test.nrc, clientset) + // Take care of adding annotations if serviceAdvertisedIP.annotations != nil { serviceAdvertisedIP.service.ObjectMeta.Annotations = serviceAdvertisedIP.annotations } + + if serviceAdvertisedIP.internalTrafficPolicy != nil { + serviceAdvertisedIP.service.Spec.InternalTrafficPolicy = serviceAdvertisedIP.internalTrafficPolicy + } + + if serviceAdvertisedIP.externalTrafficPolicy != nil { + serviceAdvertisedIP.service.Spec.ExternalTrafficPolicy = *serviceAdvertisedIP.externalTrafficPolicy + } + + // Take care of adding endpoints if needed for test + if endpoints != nil { + endpoints.ObjectMeta.Name = serviceAdvertisedIP.service.Name + endpoints.ObjectMeta.Namespace = serviceAdvertisedIP.service.Namespace + if _, err := clientset.CoreV1().Endpoints(endpoints.GetObjectMeta().GetNamespace()).Create( + context.Background(), endpoints, metav1.CreateOptions{}); err != nil { + t.Fatalf("failed to create endpoints for test: %v", err) + } + waitForListerWithTimeout(test.nrc.epLister, time.Second*10, t) + } + svc, _ := clientset.CoreV1().Services("default").Create(context.Background(), serviceAdvertisedIP.service, metav1.CreateOptions{}) - advertisedIPs, withdrawnIPs, _ := nrc.getVIPsForService(svc, false) + advertisedIPs, withdrawnIPs, err := test.nrc.getAllVIPsForService(svc) + if err != nil { + t.Errorf("We shouldn't get an error for any of these tests, failing due to: %v", err) + } t.Logf("AdvertisedIPs: %v\n", advertisedIPs) t.Logf("WithdrawnIPs: %v\n", withdrawnIPs) if !Equal(serviceAdvertisedIP.advertisedIPs, advertisedIPs) { @@ -373,3 +914,157 @@ func Test_getVIPsForService(t *testing.T) { }) } } + +func getClusterSvc() *v1core.Service { + return &v1core.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-cluster", + Namespace: "default", + }, + Spec: v1core.ServiceSpec{ + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + } +} + +func getExternalSvc() *v1core.Service { + return &v1core.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-external", + Namespace: "default", + }, + Spec: v1core.ServiceSpec{ + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + } +} + +func getNodePortSvc() *v1core.Service { + return &v1core.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-nodeport", + Namespace: "default", + }, + Spec: v1core.ServiceSpec{ + Type: NodePortST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + } +} + +func getLoadBalancerSvc() *v1core.Service { + return &v1core.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-loadbalancer", + Namespace: "default", + }, + Spec: v1core.ServiceSpec{ + Type: LoadBalancerST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + Status: v1core.ServiceStatus{ + LoadBalancer: v1core.LoadBalancerStatus{ + Ingress: []v1core.LoadBalancerIngress{ + { + IP: "10.0.255.1", + }, + { + IP: "10.0.255.2", + }, + }, + }, + }, + } +} + +func getContainsLocalIPv4EPs() *v1core.Endpoints { + return &v1core.Endpoints{ + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + { + IP: "10.1.0.2", + }, + }, + }, + { + Addresses: []v1core.EndpointAddress{ + { + IP: "10.1.1.1", + }, + }, + }, + }, + } +} + +func getContainsLocalIPv6EPs() *v1core.Endpoints { + return &v1core.Endpoints{ + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv6, + }, + { + IP: "2001:db8:42:2::2", + }, + }, + }, + { + Addresses: []v1core.EndpointAddress{ + { + IP: "2001:db8:42:2::3", + }, + }, + }, + }, + } +} + +func getNoLocalAddressesEPs() *v1core.Endpoints { + return &v1core.Endpoints{ + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: "2001:db8:42:2::3", + }, + { + IP: "2001:db8:42:2::2", + }, + }, + }, + { + Addresses: []v1core.EndpointAddress{ + { + IP: "2001:db8:42:2::3", + }, + }, + }, + { + Addresses: []v1core.EndpointAddress{ + { + IP: "10.1.0.2", + }, + }, + }, + }, + } +} diff --git a/pkg/controllers/routing/network_routes_controller_test.go b/pkg/controllers/routing/network_routes_controller_test.go index 95c0b2366..82c8ca653 100644 --- a/pkg/controllers/routing/network_routes_controller_test.go +++ b/pkg/controllers/routing/network_routes_controller_test.go @@ -23,9 +23,10 @@ import ( func Test_advertiseClusterIPs(t *testing.T) { testcases := []struct { - name string - nrc *NetworkRoutingController - existingServices []*v1core.Service + name string + nrc *NetworkRoutingController + existingServices []*v1core.Service + existingEndpoints []*v1core.Endpoints // the key is the subnet from the watch event watchEvents map[string]bool }{ @@ -34,16 +35,39 @@ func Test_advertiseClusterIPs(t *testing.T) { "add bgp path for service with ClusterIP", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -55,34 +79,93 @@ func Test_advertiseClusterIPs(t *testing.T) { "add bgp path for service with ClusterIP/NodePort/LoadBalancer", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.2", + Type: LoadBalancerST, + ClusterIP: "10.0.0.2", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: NodePortST, - ClusterIP: "10.0.0.3", + Type: NodePortST, + ClusterIP: "10.0.0.3", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -96,16 +179,22 @@ func Test_advertiseClusterIPs(t *testing.T) { "add bgp path for invalid service type", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { @@ -113,8 +202,42 @@ func Test_advertiseClusterIPs(t *testing.T) { Name: "svc-2", }, Spec: v1core.ServiceSpec{ - Type: "AnotherType", - ClusterIP: "10.0.0.2", + Type: "AnotherType", + ClusterIP: "10.0.0.2", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -126,34 +249,93 @@ func Test_advertiseClusterIPs(t *testing.T) { "add bgp path for headless service", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "None", + Type: ClusterIPST, + ClusterIP: "None", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "", + Type: ClusterIPST, + ClusterIP: "", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -168,7 +350,7 @@ func Test_advertiseClusterIPs(t *testing.T) { go testcase.nrc.bgpServer.Serve() global := &gobgpapi.Global{ Asn: 1, - RouterId: "10.0.0.0", + RouterId: testNodeIPv4, ListenPort: 10000, } err := testcase.nrc.bgpServer.StartBgp(context.Background(), &gobgpapi.StartBgpRequest{Global: global}) @@ -189,6 +371,11 @@ func Test_advertiseClusterIPs(t *testing.T) { t.Fatalf("failed to create existing services: %v", err) } + err = createEndpoints(clientset, testcase.existingEndpoints) + if err != nil { + t.Fatalf("failed to create existing endpoints: %v", err) + } + waitForListerWithTimeout(testcase.nrc.svcLister, time.Second*10, t) var events []*gobgpapi.Path @@ -218,7 +405,7 @@ func Test_advertiseClusterIPs(t *testing.T) { testcase.nrc.advertiseExternalIP = false testcase.nrc.advertiseLoadBalancerIP = false - toAdvertise, toWithdraw, _ := testcase.nrc.getActiveVIPs() + toAdvertise, toWithdraw, _ := testcase.nrc.getVIPs() testcase.nrc.advertiseVIPs(toAdvertise) testcase.nrc.withdrawVIPs(toWithdraw) @@ -253,9 +440,10 @@ func Test_advertiseClusterIPs(t *testing.T) { func Test_advertiseExternalIPs(t *testing.T) { testcases := []struct { - name string - nrc *NetworkRoutingController - existingServices []*v1core.Service + name string + nrc *NetworkRoutingController + existingServices []*v1core.Service + existingEndpoints []*v1core.Endpoints // the key is the subnet from the watch event watchEvents map[string]bool }{ @@ -264,16 +452,39 @@ func Test_advertiseExternalIPs(t *testing.T) { &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), primaryIP: net.ParseIP("10.0.0.1"), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -286,37 +497,96 @@ func Test_advertiseExternalIPs(t *testing.T) { "add bgp path for services with external IPs of type ClusterIP/NodePort/LoadBalancer", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.2", - ExternalIPs: []string{"2.2.2.2"}, + Type: LoadBalancerST, + ClusterIP: "10.0.0.2", + ExternalIPs: []string{"2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: NodePortST, - ClusterIP: "10.0.0.3", - ExternalIPs: []string{"3.3.3.3", "4.4.4.4"}, + Type: NodePortST, + ClusterIP: "10.0.0.3", + ExternalIPs: []string{"3.3.3.3", "4.4.4.4"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -331,27 +601,68 @@ func Test_advertiseExternalIPs(t *testing.T) { "add bgp path for invalid service type", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: "AnotherType", - ClusterIP: "10.0.0.2", - ExternalIPs: []string{"2.2.2.2"}, + Type: "AnotherType", + ClusterIP: "10.0.0.2", + ExternalIPs: []string{"2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -363,37 +674,96 @@ func Test_advertiseExternalIPs(t *testing.T) { "add bgp path for headless service", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "None", - ExternalIPs: []string{"2.2.2.2"}, + Type: ClusterIPST, + ClusterIP: "None", + ExternalIPs: []string{"2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "", - ExternalIPs: []string{"3.3.3.3"}, + Type: ClusterIPST, + ClusterIP: "", + ExternalIPs: []string{"3.3.3.3"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, + }, + }, + }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, }, }, }, @@ -405,16 +775,22 @@ func Test_advertiseExternalIPs(t *testing.T) { "skip bgp path to loadbalancerIP for service without LoadBalancer IP", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.1", + Type: LoadBalancerST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -427,22 +803,45 @@ func Test_advertiseExternalIPs(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{}, }, { "add bgp path to loadbalancerIP for service with LoadBalancer IP", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.1", + Type: LoadBalancerST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -458,6 +857,23 @@ func Test_advertiseExternalIPs(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{ "10.0.255.1/32": true, "10.0.255.2/32": true, @@ -467,16 +883,22 @@ func Test_advertiseExternalIPs(t *testing.T) { "no bgp path to nil loadbalancerIPs for service with LoadBalancer", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.1", + Type: LoadBalancerST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -485,25 +907,48 @@ func Test_advertiseExternalIPs(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{}, }, { "no bgp path to loadbalancerIPs for service with LoadBalancer and skiplbips annotation", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", Annotations: map[string]string{ svcSkipLbIpsAnnotation: "true", }, }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.1", + Type: LoadBalancerST, + ClusterIP: "10.0.0.1", + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -519,17 +964,33 @@ func Test_advertiseExternalIPs(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{}, }, } - //nolint:dupl // There is no need to spend a lot of time de-duplicating test code for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { go testcase.nrc.bgpServer.Serve() global := &gobgpapi.Global{ Asn: 1, - RouterId: "10.0.0.0", + RouterId: testNodeIPv4, ListenPort: 10000, } err := testcase.nrc.bgpServer.StartBgp(context.Background(), &gobgpapi.StartBgpRequest{Global: global}) @@ -572,6 +1033,11 @@ func Test_advertiseExternalIPs(t *testing.T) { t.Fatalf("failed to create existing services: %v", err) } + err = createEndpoints(clientset, testcase.existingEndpoints) + if err != nil { + t.Fatalf("failed to create existing endpoints: %v", err) + } + waitForListerWithTimeout(testcase.nrc.svcLister, time.Second*10, t) // ExternalIPs @@ -579,7 +1045,7 @@ func Test_advertiseExternalIPs(t *testing.T) { testcase.nrc.advertiseExternalIP = true testcase.nrc.advertiseLoadBalancerIP = true - toAdvertise, toWithdraw, _ := testcase.nrc.getActiveVIPs() + toAdvertise, toWithdraw, _ := testcase.nrc.getVIPs() testcase.nrc.advertiseVIPs(toAdvertise) testcase.nrc.withdrawVIPs(toWithdraw) timeoutCh := time.After(time.Second * 10) @@ -614,9 +1080,10 @@ func Test_advertiseExternalIPs(t *testing.T) { func Test_advertiseAnnotationOptOut(t *testing.T) { testcases := []struct { - name string - nrc *NetworkRoutingController - existingServices []*v1core.Service + name string + nrc *NetworkRoutingController + existingServices []*v1core.Service + existingEndpoints []*v1core.Endpoints // the key is the subnet from the watch event watchEvents map[string]bool }{ @@ -624,37 +1091,49 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { "add bgp paths for all service IPs", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.1.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: NodePortST, - ClusterIP: "10.0.0.2", - ExternalIPs: []string{"2.2.2.2", "3.3.3.3"}, + Type: NodePortST, + ClusterIP: "10.0.0.2", + ExternalIPs: []string{"2.2.2.2", "3.3.3.3"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.3", - ExternalIPs: []string{"4.4.4.4"}, + Type: LoadBalancerST, + ClusterIP: "10.0.0.3", + ExternalIPs: []string{"4.4.4.4"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -670,6 +1149,53 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{ "10.0.0.1/32": true, "10.0.0.2/32": true, @@ -686,12 +1212,16 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { "opt out to advertise any IPs via annotations", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.1.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", Annotations: map[string]string{ svcAdvertiseClusterAnnotation: "false", svcAdvertiseExternalAnnotation: "false", @@ -699,9 +1229,11 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { }, }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + Type: LoadBalancerST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -717,11 +1249,27 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{}, }, } - //nolint:dupl // There is no need to spend a lot of time de-duplicating test code for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { go testcase.nrc.bgpServer.Serve() @@ -771,6 +1319,11 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { t.Fatalf("failed to create existing services: %v", err) } + err = createEndpoints(clientset, testcase.existingEndpoints) + if err != nil { + t.Fatalf("failed to create existing endpoints: %v", err) + } + waitForListerWithTimeout(testcase.nrc.svcLister, time.Second*10, t) // By default advertise all IPs @@ -778,7 +1331,7 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { testcase.nrc.advertiseExternalIP = true testcase.nrc.advertiseLoadBalancerIP = true - toAdvertise, toWithdraw, _ := testcase.nrc.getActiveVIPs() + toAdvertise, toWithdraw, _ := testcase.nrc.getVIPs() testcase.nrc.advertiseVIPs(toAdvertise) testcase.nrc.withdrawVIPs(toWithdraw) timeoutCh := time.After(time.Second * 10) @@ -813,9 +1366,10 @@ func Test_advertiseAnnotationOptOut(t *testing.T) { func Test_advertiseAnnotationOptIn(t *testing.T) { testcases := []struct { - name string - nrc *NetworkRoutingController - existingServices []*v1core.Service + name string + nrc *NetworkRoutingController + existingServices []*v1core.Service + existingEndpoints []*v1core.Endpoints // the key is the subnet from the watch event watchEvents map[string]bool }{ @@ -823,39 +1377,51 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { "no bgp paths for any service IPs", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.1.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: NodePortST, - ClusterIP: "10.0.0.2", - ExternalIPs: []string{"2.2.2.2", "3.3.3.3"}, + Type: NodePortST, + ClusterIP: "10.0.0.2", + ExternalIPs: []string{"2.2.2.2", "3.3.3.3"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", }, Spec: v1core.ServiceSpec{ Type: LoadBalancerST, ClusterIP: "10.0.0.3", // ignored since LoadBalancer services don't // advertise external IPs. - ExternalIPs: []string{"4.4.4.4"}, + ExternalIPs: []string{"4.4.4.4"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -871,18 +1437,69 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{}, }, { "opt in to advertise all IPs via annotations", &NetworkRoutingController{ bgpServer: gobgp.NewBgpServer(), - primaryIP: net.ParseIP("10.0.1.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, []*v1core.Service{ { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-1", + Name: "svc-1", + Namespace: "default", Annotations: map[string]string{ svcAdvertiseClusterAnnotation: "true", svcAdvertiseExternalAnnotation: "true", @@ -890,14 +1507,17 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { }, }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-2", + Name: "svc-2", + Namespace: "default", Annotations: map[string]string{ svcAdvertiseClusterAnnotation: "true", svcAdvertiseExternalAnnotation: "true", @@ -905,14 +1525,17 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { }, }, Spec: v1core.ServiceSpec{ - Type: NodePortST, - ClusterIP: "10.0.0.2", - ExternalIPs: []string{"2.2.2.2", "3.3.3.3"}, + Type: NodePortST, + ClusterIP: "10.0.0.2", + ExternalIPs: []string{"2.2.2.2", "3.3.3.3"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: "svc-3", + Name: "svc-3", + Namespace: "default", Annotations: map[string]string{ svcAdvertiseClusterAnnotation: "true", svcAdvertiseExternalAnnotation: "true", @@ -920,9 +1543,11 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { }, }, Spec: v1core.ServiceSpec{ - Type: LoadBalancerST, - ClusterIP: "10.0.0.3", - ExternalIPs: []string{"4.4.4.4"}, + Type: LoadBalancerST, + ClusterIP: "10.0.0.3", + ExternalIPs: []string{"4.4.4.4"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, Status: v1core.ServiceStatus{ LoadBalancer: v1core.LoadBalancerStatus{ @@ -938,6 +1563,53 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { }, }, }, + []*v1core.Endpoints{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-1", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-2", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-3", + Namespace: "default", + }, + Subsets: []v1core.EndpointSubset{ + { + Addresses: []v1core.EndpointAddress{ + { + IP: testNodeIPv4, + }, + }, + }, + }, + }, + }, map[string]bool{ "10.0.0.1/32": true, "10.0.0.2/32": true, @@ -952,7 +1624,6 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { }, } - //nolint:dupl // There is no need to spend a lot of time de-duplicating test code for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { go testcase.nrc.bgpServer.Serve() @@ -1002,6 +1673,11 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { t.Fatalf("failed to create existing services: %v", err) } + err = createEndpoints(clientset, testcase.existingEndpoints) + if err != nil { + t.Fatalf("failed to create existing endpoints: %v", err) + } + waitForListerWithTimeout(testcase.nrc.svcLister, time.Second*10, t) // By default do not advertise any IPs @@ -1009,7 +1685,7 @@ func Test_advertiseAnnotationOptIn(t *testing.T) { testcase.nrc.advertiseExternalIP = false testcase.nrc.advertiseLoadBalancerIP = false - toAdvertise, toWithdraw, _ := testcase.nrc.getActiveVIPs() + toAdvertise, toWithdraw, _ := testcase.nrc.getVIPs() testcase.nrc.advertiseVIPs(toAdvertise) testcase.nrc.withdrawVIPs(toWithdraw) @@ -1055,7 +1731,11 @@ func Test_nodeHasEndpointsForService(t *testing.T) { { "node has endpoints for service", &NetworkRoutingController{ - nodeName: "node-1", + nodeName: "node-1", + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, &v1core.Service{ ObjectMeta: metav1.ObjectMeta{ @@ -1063,9 +1743,11 @@ func Test_nodeHasEndpointsForService(t *testing.T) { Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, &v1core.Endpoints{ @@ -1094,7 +1776,11 @@ func Test_nodeHasEndpointsForService(t *testing.T) { { "node has no endpoints for service", &NetworkRoutingController{ - nodeName: "node-1", + nodeName: "node-1", + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, &v1core.Service{ ObjectMeta: metav1.ObjectMeta{ @@ -1102,9 +1788,11 @@ func Test_nodeHasEndpointsForService(t *testing.T) { Namespace: "default", }, Spec: v1core.ServiceSpec{ - Type: ClusterIPST, - ClusterIP: "10.0.0.1", - ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + Type: ClusterIPST, + ClusterIP: "10.0.0.1", + ExternalIPs: []string{"1.1.1.1", "2.2.2.2"}, + InternalTrafficPolicy: &testClusterIntTrafPol, + ExternalTrafficPolicy: testClusterExtTrafPol, }, }, &v1core.Endpoints{ @@ -1183,7 +1871,10 @@ func Test_advertisePodRoute(t *testing.T) { podCidr: "172.20.0.0/24", isIPv4Capable: true, podIPv4CIDRs: []string{"172.20.0.0/24"}, - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, "node-1", &v1core.Node{ @@ -1210,7 +1901,10 @@ func Test_advertisePodRoute(t *testing.T) { podCidr: "172.20.0.0/24", isIPv4Capable: true, podIPv4CIDRs: []string{"172.20.0.0/24"}, - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, "", &v1core.Node{ @@ -1240,7 +1934,10 @@ func Test_advertisePodRoute(t *testing.T) { v1core.NodeInternalIP: {net.IPv6loopback}, }, isIPv6Capable: true, - primaryIP: net.ParseIP("10.0.0.1"), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, }, "", &v1core.Node{ @@ -1303,7 +2000,7 @@ func Test_advertisePodRoute(t *testing.T) { go testcase.nrc.bgpServer.Serve() global := &gobgpapi.Global{ Asn: 1, - RouterId: "10.0.0.0", + RouterId: testNodeIPv4, ListenPort: 10000, } err := testcase.nrc.bgpServer.StartBgp(context.Background(), &gobgpapi.StartBgpRequest{Global: global}) @@ -1398,9 +2095,12 @@ func Test_syncInternalPeers(t *testing.T) { &NetworkRoutingController{ bgpFullMeshMode: true, clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - bgpServer: gobgp.NewBgpServer(), - activeNodes: make(map[string]bool), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + bgpServer: gobgp.NewBgpServer(), + activeNodes: make(map[string]bool), }, []*v1core.Node{ { @@ -1426,9 +2126,12 @@ func Test_syncInternalPeers(t *testing.T) { &NetworkRoutingController{ bgpFullMeshMode: true, clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - bgpServer: gobgp.NewBgpServer(), - activeNodes: make(map[string]bool), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + bgpServer: gobgp.NewBgpServer(), + activeNodes: make(map[string]bool), }, []*v1core.Node{ { @@ -1468,8 +2171,11 @@ func Test_syncInternalPeers(t *testing.T) { &NetworkRoutingController{ bgpFullMeshMode: true, clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - bgpServer: gobgp.NewBgpServer(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + bgpServer: gobgp.NewBgpServer(), activeNodes: map[string]bool{ "10.0.0.2": true, }, @@ -1498,10 +2204,13 @@ func Test_syncInternalPeers(t *testing.T) { &NetworkRoutingController{ bgpFullMeshMode: false, clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - bgpServer: gobgp.NewBgpServer(), - activeNodes: make(map[string]bool), - nodeAsnNumber: 100, + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + bgpServer: gobgp.NewBgpServer(), + activeNodes: make(map[string]bool), + nodeAsnNumber: 100, }, []*v1core.Node{ { @@ -1545,7 +2254,7 @@ func Test_syncInternalPeers(t *testing.T) { go testcase.nrc.bgpServer.Serve() global := &gobgpapi.Global{ Asn: 1, - RouterId: "10.0.0.0", + RouterId: testNodeIPv4, ListenPort: 10000, } err := testcase.nrc.bgpServer.StartBgp(context.Background(), &gobgpapi.StartBgpRequest{Global: global}) @@ -1604,11 +2313,14 @@ func Test_routeReflectorConfiguration(t *testing.T) { { "RR server with int cluster id", &NetworkRoutingController{ - bgpFullMeshMode: false, - bgpPort: 10000, - clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - routerID: "10.0.0.0", + bgpFullMeshMode: false, + bgpPort: 10000, + clientset: fake.NewSimpleClientset(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + routerID: testNodeIPv4, bgpServer: gobgp.NewBgpServer(), activeNodes: make(map[string]bool), nodeAsnNumber: 100, @@ -1631,11 +2343,14 @@ func Test_routeReflectorConfiguration(t *testing.T) { { "RR server with IPv4 cluster id", &NetworkRoutingController{ - bgpFullMeshMode: false, - bgpPort: 10000, - clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - routerID: "10.0.0.0", + bgpFullMeshMode: false, + bgpPort: 10000, + clientset: fake.NewSimpleClientset(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + routerID: testNodeIPv4, bgpServer: gobgp.NewBgpServer(), activeNodes: make(map[string]bool), nodeAsnNumber: 100, @@ -1658,11 +2373,14 @@ func Test_routeReflectorConfiguration(t *testing.T) { { "RR client with int cluster id", &NetworkRoutingController{ - bgpFullMeshMode: false, - bgpPort: 10000, - clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - routerID: "10.0.0.0", + bgpFullMeshMode: false, + bgpPort: 10000, + clientset: fake.NewSimpleClientset(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + routerID: testNodeIPv4, bgpServer: gobgp.NewBgpServer(), activeNodes: make(map[string]bool), nodeAsnNumber: 100, @@ -1685,11 +2403,14 @@ func Test_routeReflectorConfiguration(t *testing.T) { { "RR client with IPv4 cluster id", &NetworkRoutingController{ - bgpFullMeshMode: false, - bgpPort: 10000, - clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), - routerID: "10.0.0.0", + bgpFullMeshMode: false, + bgpPort: 10000, + clientset: fake.NewSimpleClientset(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, + routerID: testNodeIPv4, bgpServer: gobgp.NewBgpServer(), activeNodes: make(map[string]bool), nodeAsnNumber: 100, @@ -1712,10 +2433,13 @@ func Test_routeReflectorConfiguration(t *testing.T) { { "RR server with unparseable cluster id", &NetworkRoutingController{ - bgpFullMeshMode: false, - bgpPort: 10000, - clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), + bgpFullMeshMode: false, + bgpPort: 10000, + clientset: fake.NewSimpleClientset(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, bgpServer: gobgp.NewBgpServer(), activeNodes: make(map[string]bool), nodeAsnNumber: 100, @@ -1738,10 +2462,13 @@ func Test_routeReflectorConfiguration(t *testing.T) { { "RR client with unparseable cluster id", &NetworkRoutingController{ - bgpFullMeshMode: false, - bgpPort: 10000, - clientset: fake.NewSimpleClientset(), - primaryIP: net.ParseIP("10.0.0.0"), + bgpFullMeshMode: false, + bgpPort: 10000, + clientset: fake.NewSimpleClientset(), + primaryIP: net.ParseIP(testNodeIPv4), + nodeIPv4Addrs: map[v1core.NodeAddressType][]net.IP{v1core.NodeInternalIP: { + net.ParseIP(testNodeIPv4)}, + }, bgpServer: gobgp.NewBgpServer(), activeNodes: make(map[string]bool), nodeAsnNumber: 100, @@ -2003,7 +2730,7 @@ func Test_generateTunnelName(t *testing.T) { func createServices(clientset kubernetes.Interface, svcs []*v1core.Service) error { for _, svc := range svcs { - _, err := clientset.CoreV1().Services("default").Create(context.Background(), svc, metav1.CreateOptions{}) + _, err := clientset.CoreV1().Services(svc.ObjectMeta.Namespace).Create(context.Background(), svc, metav1.CreateOptions{}) if err != nil { return err } @@ -2023,6 +2750,18 @@ func createNodes(clientset kubernetes.Interface, nodes []*v1core.Node) error { return nil } +func createEndpoints(clientset kubernetes.Interface, endpoints []*v1core.Endpoints) error { + for _, eps := range endpoints { + _, err := clientset.CoreV1().Endpoints(eps.ObjectMeta.Namespace).Create( + context.Background(), eps, metav1.CreateOptions{}) + if err != nil { + return err + } + } + + return nil +} + func startInformersForRoutes(nrc *NetworkRoutingController, clientset kubernetes.Interface) { informerFactory := informers.NewSharedInformerFactory(clientset, 0) svcInformer := informerFactory.Core().V1().Services().Informer()