diff --git a/pkg/proxy/endpoints_test.go b/pkg/proxy/endpoints_test.go index 664a804c646..6c1602d4e3e 100644 --- a/pkg/proxy/endpoints_test.go +++ b/pkg/proxy/endpoints_test.go @@ -133,183 +133,259 @@ func makeTestEndpoints(namespace, name string, eptFunc func(*api.Endpoints)) *ap func TestEndpointsToEndpointsMap(t *testing.T) { epTracker := NewEndpointChangeTracker("test-hostname", nil, nil, nil) + trueVal := true + falseVal := false + testCases := []struct { + desc string newEndpoints *api.Endpoints expected map[ServicePortName][]*EndpointInfoCommon - }{{ - // Case[0]: nothing - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) {}), - expected: map[ServicePortName][]*EndpointInfoCommon{}, - }, { - // Case[1]: no changes, unnamed port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }}, - Ports: []api.EndpointPort{{ - Name: "", - Port: 11, - }}, + isIPv6Mode *bool + }{ + { + desc: "nothing", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) {}), + expected: map[ServicePortName][]*EndpointInfoCommon{}, + }, + { + desc: "no changes, unnamed port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }}, + Ports: []api.EndpointPort{{ + Name: "", + Port: 11, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", ""): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", ""): { - {Endpoint: "1.1.1.1:11", IsLocal: false}, }, }, - }, { - // Case[2]: no changes, named port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }}, - Ports: []api.EndpointPort{{ - Name: "port", - Port: 11, - }}, + { + desc: "no changes, named port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }}, + Ports: []api.EndpointPort{{ + Name: "port", + Port: 11, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "port"): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", "port"): { - {Endpoint: "1.1.1.1:11", IsLocal: false}, }, }, - }, { - // Case[3]: new port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }}, - Ports: []api.EndpointPort{{ - Port: 11, - }}, + { + desc: "new port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }}, + Ports: []api.EndpointPort{{ + Port: 11, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", ""): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", ""): { - {Endpoint: "1.1.1.1:11", IsLocal: false}, }, }, - }, { - // Case[4]: remove port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) {}), - expected: map[ServicePortName][]*EndpointInfoCommon{}, - }, { - // Case[5]: new IP and port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }, { - IP: "2.2.2.2", - }}, - Ports: []api.EndpointPort{{ - Name: "p1", - Port: 11, - }, { - Name: "p2", - Port: 22, - }}, + { + desc: "remove port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) {}), + expected: map[ServicePortName][]*EndpointInfoCommon{}, + }, + { + desc: "new IP and port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }, { + IP: "2.2.2.2", + }}, + Ports: []api.EndpointPort{{ + Name: "p1", + Port: 11, + }, { + Name: "p2", + Port: 22, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "p1"): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, + {Endpoint: "2.2.2.2:11", IsLocal: false}, + }, + makeServicePortName("ns1", "ep1", "p2"): { + {Endpoint: "1.1.1.1:22", IsLocal: false}, + {Endpoint: "2.2.2.2:22", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", "p1"): { - {Endpoint: "1.1.1.1:11", IsLocal: false}, - {Endpoint: "2.2.2.2:11", IsLocal: false}, - }, - makeServicePortName("ns1", "ep1", "p2"): { - {Endpoint: "1.1.1.1:22", IsLocal: false}, - {Endpoint: "2.2.2.2:22", IsLocal: false}, }, }, - }, { - // Case[6]: remove IP and port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }}, - Ports: []api.EndpointPort{{ - Name: "p1", - Port: 11, - }}, + { + desc: "remove IP and port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }}, + Ports: []api.EndpointPort{{ + Name: "p1", + Port: 11, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "p1"): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", "p1"): { - {Endpoint: "1.1.1.1:11", IsLocal: false}, }, }, - }, { - // Case[7]: rename port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }}, - Ports: []api.EndpointPort{{ - Name: "p2", - Port: 11, - }}, + { + desc: "rename port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }}, + Ports: []api.EndpointPort{{ + Name: "p2", + Port: 11, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "p2"): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", "p2"): { - {Endpoint: "1.1.1.1:11", IsLocal: false}, }, }, - }, { - // Case[8]: renumber port - newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { - ept.Subsets = []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{ - IP: "1.1.1.1", - }}, - Ports: []api.EndpointPort{{ - Name: "p1", - Port: 22, - }}, + { + desc: "renumber port", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }}, + Ports: []api.EndpointPort{{ + Name: "p1", + Port: 22, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "p1"): { + {Endpoint: "1.1.1.1:22", IsLocal: false}, }, - } - }), - expected: map[ServicePortName][]*EndpointInfoCommon{ - makeServicePortName("ns1", "ep1", "p1"): { - {Endpoint: "1.1.1.1:22", IsLocal: false}, }, }, - }} + { + desc: "should omit IPv6 address in IPv4 mode", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }, { + IP: "2001:db8:85a3:0:0:8a2e:370:7334", + }}, + Ports: []api.EndpointPort{{ + Name: "p1", + Port: 11, + }, { + Name: "p2", + Port: 22, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "p1"): { + {Endpoint: "1.1.1.1:11", IsLocal: false}, + }, + makeServicePortName("ns1", "ep1", "p2"): { + {Endpoint: "1.1.1.1:22", IsLocal: false}, + }, + }, + isIPv6Mode: &falseVal, + }, + { + desc: "should omit IPv4 address in IPv6 mode", + newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{ + IP: "1.1.1.1", + }, { + IP: "2001:db8:85a3:0:0:8a2e:370:7334", + }}, + Ports: []api.EndpointPort{{ + Name: "p1", + Port: 11, + }, { + Name: "p2", + Port: 22, + }}, + }, + } + }), + expected: map[ServicePortName][]*EndpointInfoCommon{ + makeServicePortName("ns1", "ep1", "p1"): { + {Endpoint: "[2001:db8:85a3:0:0:8a2e:370:7334]:11", IsLocal: false}, + }, + makeServicePortName("ns1", "ep1", "p2"): { + {Endpoint: "[2001:db8:85a3:0:0:8a2e:370:7334]:22", IsLocal: false}, + }, + }, + isIPv6Mode: &trueVal, + }, + } - for tci, tc := range testCases { + for _, tc := range testCases { + epTracker.isIPv6Mode = tc.isIPv6Mode // outputs newEndpoints := epTracker.endpointsToEndpointsMap(tc.newEndpoints) if len(newEndpoints) != len(tc.expected) { - t.Errorf("[%d] expected %d new, got %d: %v", tci, len(tc.expected), len(newEndpoints), spew.Sdump(newEndpoints)) + t.Errorf("[%s] expected %d new, got %d: %v", tc.desc, len(tc.expected), len(newEndpoints), spew.Sdump(newEndpoints)) } for x := range tc.expected { if len(newEndpoints[x]) != len(tc.expected[x]) { - t.Errorf("[%d] expected %d endpoints for %v, got %d", tci, len(tc.expected[x]), x, len(newEndpoints[x])) + t.Errorf("[%s] expected %d endpoints for %v, got %d", tc.desc, len(tc.expected[x]), x, len(newEndpoints[x])) } else { for i := range newEndpoints[x] { ep := newEndpoints[x][i].(*EndpointInfoCommon) if *ep != *(tc.expected[x][i]) { - t.Errorf("[%d] expected new[%v][%d] to be %v, got %v", tci, x, i, tc.expected[x][i], *ep) + t.Errorf("[%s] expected new[%v][%d] to be %v, got %v", tc.desc, x, i, tc.expected[x][i], *ep) } } } diff --git a/pkg/proxy/service_test.go b/pkg/proxy/service_test.go index 0a24b1c0fee..03b85d12d0c 100644 --- a/pkg/proxy/service_test.go +++ b/pkg/proxy/service_test.go @@ -25,12 +25,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/sets" api "k8s.io/kubernetes/pkg/apis/core" ) const testHostname = "test-hostname" -func makeTestServiceInfo(clusterIP string, port int, protocol string, healthcheckNodePort int) *ServiceInfoCommon { +func makeTestServiceInfo(clusterIP string, port int, protocol string, healthcheckNodePort int, svcInfoFuncs ...func(*ServiceInfoCommon)) *ServiceInfoCommon { info := &ServiceInfoCommon{ ClusterIP: net.ParseIP(clusterIP), Port: port, @@ -39,6 +40,9 @@ func makeTestServiceInfo(clusterIP string, port int, protocol string, healthchec if healthcheckNodePort != 0 { info.HealthCheckNodePort = healthcheckNodePort } + for _, svcInfoFunc := range svcInfoFuncs { + svcInfoFunc(info) + } return info } @@ -81,17 +85,28 @@ func makeServicePortName(ns, name, port string) ServicePortName { func TestServiceToServiceMap(t *testing.T) { svcTracker := NewServiceChangeTracker(nil, nil, nil) + trueVal := true + falseVal := false + testClusterIPv4 := "10.0.0.1" + testExternalIPv4 := "8.8.8.8" + testSourceRangeIPv4 := "0.0.0.0/1" + testClusterIPv6 := "2001:db8:85a3:0:0:8a2e:370:7334" + testExternalIPv6 := "2001:db8:85a3:0:0:8a2e:370:7335" + testSourceRangeIPv6 := "2001:db8::/32" + testCases := []struct { - service *api.Service - expected map[ServicePortName]*ServiceInfoCommon + desc string + service *api.Service + expected map[ServicePortName]*ServiceInfoCommon + isIPv6Mode *bool }{ { - // Case[0]: nothing + desc: "nothing", service: nil, expected: map[ServicePortName]*ServiceInfoCommon{}, }, { - // Case[1]: headless service + desc: "headless service", service: makeTestService("ns2", "headless", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeClusterIP svc.Spec.ClusterIP = api.ClusterIPNone @@ -100,7 +115,7 @@ func TestServiceToServiceMap(t *testing.T) { expected: map[ServicePortName]*ServiceInfoCommon{}, }, { - // Case[2]: headless service without port + desc: "headless service without port", service: makeTestService("ns2", "headless-without-port", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeClusterIP svc.Spec.ClusterIP = api.ClusterIPNone @@ -108,7 +123,7 @@ func TestServiceToServiceMap(t *testing.T) { expected: map[ServicePortName]*ServiceInfoCommon{}, }, { - // Case[3]: cluster ip service + desc: "cluster ip service", service: makeTestService("ns2", "cluster-ip", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeClusterIP svc.Spec.ClusterIP = "172.16.55.4" @@ -121,7 +136,7 @@ func TestServiceToServiceMap(t *testing.T) { }, }, { - // Case[4]: nodeport service + desc: "nodeport service", service: makeTestService("ns2", "node-port", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeNodePort svc.Spec.ClusterIP = "172.16.55.10" @@ -134,7 +149,7 @@ func TestServiceToServiceMap(t *testing.T) { }, }, { - // Case[5]: load balancer service + desc: "load balancer service", service: makeTestService("ns1", "load-balancer", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeLoadBalancer svc.Spec.ClusterIP = "172.16.55.11" @@ -153,7 +168,7 @@ func TestServiceToServiceMap(t *testing.T) { }, }, { - // Case[6]: load balancer service with only local traffic policy + desc: "load balancer service with only local traffic policy", service: makeTestService("ns1", "only-local-load-balancer", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeLoadBalancer svc.Spec.ClusterIP = "172.16.55.12" @@ -174,7 +189,7 @@ func TestServiceToServiceMap(t *testing.T) { }, }, { - // Case[7]: external name service + desc: "external name service", service: makeTestService("ns2", "external-name", func(svc *api.Service) { svc.Spec.Type = api.ServiceTypeExternalName svc.Spec.ClusterIP = "172.16.55.4" // Should be ignored @@ -183,22 +198,177 @@ func TestServiceToServiceMap(t *testing.T) { }), expected: map[ServicePortName]*ServiceInfoCommon{}, }, + { + desc: "service with ipv6 clusterIP under ipv4 mode, service should be filtered", + service: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "invalidIPv6InIPV4Mode", + Namespace: "test", + }, + Spec: api.ServiceSpec{ + ClusterIP: testClusterIPv6, + Ports: []api.ServicePort{ + { + Name: "testPort", + Port: int32(12345), + Protocol: api.ProtocolTCP, + }, + }, + }, + }, + isIPv6Mode: &falseVal, + }, + { + desc: "service with ipv4 clusterIP under ipv6 mode, service should be filtered", + service: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "invalidIPv4InIPV6Mode", + Namespace: "test", + }, + Spec: api.ServiceSpec{ + ClusterIP: testClusterIPv4, + Ports: []api.ServicePort{ + { + Name: "testPort", + Port: int32(12345), + Protocol: api.ProtocolTCP, + }, + }, + }, + }, + isIPv6Mode: &trueVal, + }, + { + desc: "service with ipv4 configurations under ipv4 mode", + service: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "validIPv4", + Namespace: "test", + }, + Spec: api.ServiceSpec{ + ClusterIP: testClusterIPv4, + ExternalIPs: []string{testExternalIPv4}, + LoadBalancerSourceRanges: []string{testSourceRangeIPv4}, + Ports: []api.ServicePort{ + { + Name: "testPort", + Port: int32(12345), + Protocol: api.ProtocolTCP, + }, + }, + }, + }, + expected: map[ServicePortName]*ServiceInfoCommon{ + makeServicePortName("test", "validIPv4", "testPort"): makeTestServiceInfo(testClusterIPv4, 12345, "TCP", 0, func(info *ServiceInfoCommon) { + info.ExternalIPs = []string{testExternalIPv4} + info.LoadBalancerSourceRanges = []string{testSourceRangeIPv4} + }), + }, + isIPv6Mode: &falseVal, + }, + { + desc: "service with ipv6 configurations under ipv6 mode", + service: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "validIPv6", + Namespace: "test", + }, + Spec: api.ServiceSpec{ + ClusterIP: testClusterIPv6, + ExternalIPs: []string{testExternalIPv6}, + LoadBalancerSourceRanges: []string{testSourceRangeIPv6}, + Ports: []api.ServicePort{ + { + Name: "testPort", + Port: int32(12345), + Protocol: api.ProtocolTCP, + }, + }, + }, + }, + expected: map[ServicePortName]*ServiceInfoCommon{ + makeServicePortName("test", "validIPv6", "testPort"): makeTestServiceInfo(testClusterIPv6, 12345, "TCP", 0, func(info *ServiceInfoCommon) { + info.ExternalIPs = []string{testExternalIPv6} + info.LoadBalancerSourceRanges = []string{testSourceRangeIPv6} + }), + }, + isIPv6Mode: &trueVal, + }, + { + desc: "service with both ipv4 and ipv6 configurations under ipv4 mode, ipv6 fields should be filtered", + service: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "filterIPv6InIPV4Mode", + Namespace: "test", + }, + Spec: api.ServiceSpec{ + ClusterIP: testClusterIPv4, + ExternalIPs: []string{testExternalIPv4, testExternalIPv6}, + LoadBalancerSourceRanges: []string{testSourceRangeIPv4, testSourceRangeIPv6}, + Ports: []api.ServicePort{ + { + Name: "testPort", + Port: int32(12345), + Protocol: api.ProtocolTCP, + }, + }, + }, + }, + expected: map[ServicePortName]*ServiceInfoCommon{ + makeServicePortName("test", "filterIPv6InIPV4Mode", "testPort"): makeTestServiceInfo(testClusterIPv4, 12345, "TCP", 0, func(info *ServiceInfoCommon) { + info.ExternalIPs = []string{testExternalIPv4} + info.LoadBalancerSourceRanges = []string{testSourceRangeIPv4} + }), + }, + isIPv6Mode: &falseVal, + }, + { + desc: "service with both ipv4 and ipv6 configurations under ipv6 mode, ipv4 fields should be filtered", + service: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "filterIPv4InIPV6Mode", + Namespace: "test", + }, + Spec: api.ServiceSpec{ + ClusterIP: testClusterIPv6, + ExternalIPs: []string{testExternalIPv4, testExternalIPv6}, + LoadBalancerSourceRanges: []string{testSourceRangeIPv4, testSourceRangeIPv6}, + Ports: []api.ServicePort{ + { + Name: "testPort", + Port: int32(12345), + Protocol: api.ProtocolTCP, + }, + }, + }, + }, + expected: map[ServicePortName]*ServiceInfoCommon{ + makeServicePortName("test", "filterIPv4InIPV6Mode", "testPort"): makeTestServiceInfo(testClusterIPv6, 12345, "TCP", 0, func(info *ServiceInfoCommon) { + info.ExternalIPs = []string{testExternalIPv6} + info.LoadBalancerSourceRanges = []string{testSourceRangeIPv6} + }), + }, + isIPv6Mode: &trueVal, + }, } - for tci, tc := range testCases { + for _, tc := range testCases { + svcTracker.isIPv6Mode = tc.isIPv6Mode // outputs newServices := svcTracker.serviceToServiceMap(tc.service) if len(newServices) != len(tc.expected) { - t.Errorf("[%d] expected %d new, got %d: %v", tci, len(tc.expected), len(newServices), spew.Sdump(newServices)) + t.Errorf("[%s] expected %d new, got %d: %v", tc.desc, len(tc.expected), len(newServices), spew.Sdump(newServices)) } - for x := range tc.expected { - svcInfo := newServices[x].(*ServiceInfoCommon) - if !svcInfo.ClusterIP.Equal(tc.expected[x].ClusterIP) || - svcInfo.Port != tc.expected[x].Port || - svcInfo.Protocol != tc.expected[x].Protocol || - svcInfo.HealthCheckNodePort != tc.expected[x].HealthCheckNodePort { - t.Errorf("[%d] expected new[%v]to be %v, got %v", tci, x, tc.expected[x], *svcInfo) + for svcKey, expectedInfo := range tc.expected { + svcInfo := newServices[svcKey].(*ServiceInfoCommon) + if !svcInfo.ClusterIP.Equal(expectedInfo.ClusterIP) || + svcInfo.Port != expectedInfo.Port || + svcInfo.Protocol != expectedInfo.Protocol || + svcInfo.HealthCheckNodePort != expectedInfo.HealthCheckNodePort || + !sets.NewString(svcInfo.ExternalIPs...).Equal(sets.NewString(expectedInfo.ExternalIPs...)) || + !sets.NewString(svcInfo.LoadBalancerSourceRanges...).Equal(sets.NewString(expectedInfo.LoadBalancerSourceRanges...)) { + t.Errorf("[%s] expected new[%v]to be %v, got %v", tc.desc, svcKey, expectedInfo, *svcInfo) } } }