func TestUDPProxyTimeout(t *testing.T) { lb := NewLoadBalancerRR() service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} lb.OnEndpointsUpdate([]api.Endpoints{ { ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, Ports: []api.EndpointPort{{Name: "p", Port: udpServerPort}}, }}, }, }) p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) svcInfo, err := p.addServiceOnPort(service, "UDP", 0, time.Second) if err != nil { t.Fatalf("error adding new service: %#v", err) } waitForNumProxyLoops(t, p, 1) testEchoUDP(t, "127.0.0.1", svcInfo.proxyPort) // When connecting to a UDP service endpoint, there shoule be a Conn for proxy. waitForNumProxyClients(t, svcInfo, 1, time.Second) // If conn has no activity for serviceInfo.timeout since last Read/Write, it shoule be closed because of timeout. waitForNumProxyClients(t, svcInfo, 0, 2*time.Second) }
func TestUDPProxy(t *testing.T) { lb := NewLoadBalancerRR() service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} lb.OnEndpointsUpdate([]api.Endpoints{ { ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, Ports: []api.EndpointPort{{Name: "p", Port: udpServerPort}}, }}, }, }) p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) svcInfo, err := p.addServiceOnPort(service, "UDP", 0, time.Second) if err != nil { t.Fatalf("error adding new service: %#v", err) } testEchoUDP(t, "127.0.0.1", svcInfo.proxyPort) waitForNumProxyLoops(t, p, 1) }
func TestProxyUpdatePublicIPs(t *testing.T) { lb := NewLoadBalancerRR() service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} lb.OnEndpointsUpdate([]api.Endpoints{ { ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, Ports: []api.EndpointPort{{Name: "p", Port: tcpServerPort}}, }}, }, }) p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) svcInfo, err := p.addServiceOnPort(service, "TCP", 0, time.Second) if err != nil { t.Fatalf("error adding new service: %#v", err) } testEchoTCP(t, "127.0.0.1", svcInfo.proxyPort) waitForNumProxyLoops(t, p, 1) p.OnServiceUpdate([]api.Service{{ ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Spec: api.ServiceSpec{ Ports: []api.ServicePort{{ Name: "p", Port: int32(svcInfo.portal.port), Protocol: "TCP", }}, ClusterIP: svcInfo.portal.ip.String(), ExternalIPs: []string{"4.3.2.1"}, }, }}) // Wait for the socket to actually get free. if err := waitForClosedPortTCP(p, svcInfo.proxyPort); err != nil { t.Fatalf(err.Error()) } svcInfo, exists := p.getServiceInfo(service) if !exists { t.Fatalf("can't find serviceInfo") } testEchoTCP(t, "127.0.0.1", svcInfo.proxyPort) // This is a bit async, but this should be sufficient. time.Sleep(500 * time.Millisecond) waitForNumProxyLoops(t, p, 1) }
func TestUDPProxyUpdateDeleteUpdate(t *testing.T) { lb := NewLoadBalancerRR() service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} lb.OnEndpointsUpdate([]api.Endpoints{ { ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, Ports: []api.EndpointPort{{Name: "p", Port: udpServerPort}}, }}, }, }) p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) svcInfo, err := p.addServiceOnPort(service, "UDP", 0, time.Second) if err != nil { t.Fatalf("error adding new service: %#v", err) } conn, err := net.Dial("udp", joinHostPort("", svcInfo.proxyPort)) if err != nil { t.Fatalf("error connecting to proxy: %v", err) } conn.Close() waitForNumProxyLoops(t, p, 1) p.OnServiceUpdate([]api.Service{}) if err := waitForClosedPortUDP(p, svcInfo.proxyPort); err != nil { t.Fatalf(err.Error()) } waitForNumProxyLoops(t, p, 0) p.OnServiceUpdate([]api.Service{{ ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Spec: api.ServiceSpec{ClusterIP: "1.2.3.4", Ports: []api.ServicePort{{ Name: "p", Port: int32(svcInfo.proxyPort), Protocol: "UDP", }}}, }}) svcInfo, exists := p.getServiceInfo(service) if !exists { t.Fatalf("can't find serviceInfo") } testEchoUDP(t, "127.0.0.1", svcInfo.proxyPort) waitForNumProxyLoops(t, p, 1) }
func TestMultiPortOnServiceUpdate(t *testing.T) { lb := NewLoadBalancerRR() serviceP := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} serviceQ := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "q"} serviceX := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "x"} p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) p.OnServiceUpdate([]api.Service{{ ObjectMeta: api.ObjectMeta{Name: serviceP.Name, Namespace: serviceP.Namespace}, Spec: api.ServiceSpec{ClusterIP: "1.2.3.4", Ports: []api.ServicePort{{ Name: "p", Port: 80, Protocol: "TCP", }, { Name: "q", Port: 81, Protocol: "UDP", }}}, }}) waitForNumProxyLoops(t, p, 2) svcInfo, exists := p.getServiceInfo(serviceP) if !exists { t.Fatalf("can't find serviceInfo for %s", serviceP) } if svcInfo.portal.ip.String() != "1.2.3.4" || svcInfo.portal.port != 80 || svcInfo.protocol != "TCP" { t.Errorf("unexpected serviceInfo for %s: %#v", serviceP, svcInfo) } svcInfo, exists = p.getServiceInfo(serviceQ) if !exists { t.Fatalf("can't find serviceInfo for %s", serviceQ) } if svcInfo.portal.ip.String() != "1.2.3.4" || svcInfo.portal.port != 81 || svcInfo.protocol != "UDP" { t.Errorf("unexpected serviceInfo for %s: %#v", serviceQ, svcInfo) } svcInfo, exists = p.getServiceInfo(serviceX) if exists { t.Fatalf("found unwanted serviceInfo for %s: %#v", serviceX, svcInfo) } }
func TestTCPProxyStop(t *testing.T) { lb := NewLoadBalancerRR() service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} lb.OnEndpointsUpdate([]api.Endpoints{ { ObjectMeta: api.ObjectMeta{Namespace: service.Namespace, Name: service.Name}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, Ports: []api.EndpointPort{{Name: "p", Port: tcpServerPort}}, }}, }, }) p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) svcInfo, err := p.addServiceOnPort(service, "TCP", 0, time.Second) if err != nil { t.Fatalf("error adding new service: %#v", err) } if !svcInfo.isAlive() { t.Fatalf("wrong value for isAlive(): expected true") } conn, err := net.Dial("tcp", joinHostPort("", svcInfo.proxyPort)) if err != nil { t.Fatalf("error connecting to proxy: %v", err) } conn.Close() waitForNumProxyLoops(t, p, 1) stopProxyByName(p, service) if svcInfo.isAlive() { t.Fatalf("wrong value for isAlive(): expected false") } // Wait for the port to really close. if err := waitForClosedPortTCP(p, svcInfo.proxyPort); err != nil { t.Fatalf(err.Error()) } waitForNumProxyLoops(t, p, 0) }
func TestProxyUpdatePortal(t *testing.T) { lb := NewLoadBalancerRR() service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"} lb.OnEndpointsUpdate([]api.Endpoints{ { ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, Ports: []api.EndpointPort{{Name: "p", Port: tcpServerPort}}, }}, }, }) p, err := createProxier(lb, net.ParseIP("0.0.0.0"), ipttest.NewFake(), net.ParseIP("127.0.0.1"), nil, time.Minute, udpIdleTimeoutForTest) if err != nil { t.Fatal(err) } waitForNumProxyLoops(t, p, 0) svcInfo, err := p.addServiceOnPort(service, "TCP", 0, time.Second) if err != nil { t.Fatalf("error adding new service: %#v", err) } testEchoTCP(t, "127.0.0.1", svcInfo.proxyPort) waitForNumProxyLoops(t, p, 1) p.OnServiceUpdate([]api.Service{{ ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Spec: api.ServiceSpec{ClusterIP: "", Ports: []api.ServicePort{{ Name: "p", Port: int32(svcInfo.proxyPort), Protocol: "TCP", }}}, }}) _, exists := p.getServiceInfo(service) if exists { t.Fatalf("service with empty ClusterIP should not be included in the proxy") } p.OnServiceUpdate([]api.Service{{ ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Spec: api.ServiceSpec{ClusterIP: "None", Ports: []api.ServicePort{{ Name: "p", Port: int32(svcInfo.proxyPort), Protocol: "TCP", }}}, }}) _, exists = p.getServiceInfo(service) if exists { t.Fatalf("service with 'None' as ClusterIP should not be included in the proxy") } p.OnServiceUpdate([]api.Service{{ ObjectMeta: api.ObjectMeta{Name: service.Name, Namespace: service.Namespace}, Spec: api.ServiceSpec{ClusterIP: "1.2.3.4", Ports: []api.ServicePort{{ Name: "p", Port: int32(svcInfo.proxyPort), Protocol: "TCP", }}}, }}) svcInfo, exists = p.getServiceInfo(service) if !exists { t.Fatalf("service with ClusterIP set not found in the proxy") } testEchoTCP(t, "127.0.0.1", svcInfo.proxyPort) waitForNumProxyLoops(t, p, 1) }