mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			963 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			963 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2016 The Kubernetes Authors.
 | 
						|
 | 
						|
Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
you may not use this file except in compliance with the License.
 | 
						|
You may obtain a copy of the License at
 | 
						|
 | 
						|
    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 | 
						|
Unless required by applicable law or agreed to in writing, software
 | 
						|
distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
See the License for the specific language governing permissions and
 | 
						|
limitations under the License.
 | 
						|
*/
 | 
						|
 | 
						|
package winuserspace
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io/ioutil"
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"net/http/httptest"
 | 
						|
	"net/url"
 | 
						|
	"os"
 | 
						|
	"strconv"
 | 
						|
	"sync/atomic"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"k8s.io/api/core/v1"
 | 
						|
	discovery "k8s.io/api/discovery/v1beta1"
 | 
						|
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						|
	"k8s.io/apimachinery/pkg/types"
 | 
						|
	"k8s.io/apimachinery/pkg/util/runtime"
 | 
						|
	"k8s.io/kubernetes/pkg/proxy"
 | 
						|
	netshtest "k8s.io/kubernetes/pkg/util/netsh/testing"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	udpIdleTimeoutForTest = 250 * time.Millisecond
 | 
						|
)
 | 
						|
 | 
						|
func joinHostPort(host string, port int) string {
 | 
						|
	return net.JoinHostPort(host, fmt.Sprintf("%d", port))
 | 
						|
}
 | 
						|
 | 
						|
func waitForClosedPortTCP(p *Proxier, proxyPort int) error {
 | 
						|
	for i := 0; i < 50; i++ {
 | 
						|
		conn, err := net.Dial("tcp", joinHostPort("", proxyPort))
 | 
						|
		if err != nil {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		conn.Close()
 | 
						|
		time.Sleep(1 * time.Millisecond)
 | 
						|
	}
 | 
						|
	return fmt.Errorf("port %d still open", proxyPort)
 | 
						|
}
 | 
						|
 | 
						|
func waitForClosedPortUDP(p *Proxier, proxyPort int) error {
 | 
						|
	for i := 0; i < 50; i++ {
 | 
						|
		conn, err := net.Dial("udp", joinHostPort("", proxyPort))
 | 
						|
		if err != nil {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		conn.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
 | 
						|
		// To detect a closed UDP port write, then read.
 | 
						|
		_, err = conn.Write([]byte("x"))
 | 
						|
		if err != nil {
 | 
						|
			if e, ok := err.(net.Error); ok && !e.Timeout() {
 | 
						|
				return nil
 | 
						|
			}
 | 
						|
		}
 | 
						|
		var buf [4]byte
 | 
						|
		_, err = conn.Read(buf[0:])
 | 
						|
		if err != nil {
 | 
						|
			if e, ok := err.(net.Error); ok && !e.Timeout() {
 | 
						|
				return nil
 | 
						|
			}
 | 
						|
		}
 | 
						|
		conn.Close()
 | 
						|
		time.Sleep(1 * time.Millisecond)
 | 
						|
	}
 | 
						|
	return fmt.Errorf("port %d still open", proxyPort)
 | 
						|
}
 | 
						|
 | 
						|
// udpEchoServer is a simple echo server in UDP, intended for testing the proxy.
 | 
						|
type udpEchoServer struct {
 | 
						|
	net.PacketConn
 | 
						|
}
 | 
						|
 | 
						|
func newUDPEchoServer() (*udpEchoServer, error) {
 | 
						|
	packetconn, err := net.ListenPacket("udp", ":0")
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return &udpEchoServer{packetconn}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (r *udpEchoServer) Loop() {
 | 
						|
	var buffer [4096]byte
 | 
						|
	for {
 | 
						|
		n, cliAddr, err := r.ReadFrom(buffer[0:])
 | 
						|
		if err != nil {
 | 
						|
			fmt.Printf("ReadFrom failed: %v\n", err)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		r.WriteTo(buffer[0:n], cliAddr)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
var tcpServerPort int32
 | 
						|
var udpServerPort int32
 | 
						|
 | 
						|
func TestMain(m *testing.M) {
 | 
						|
	// Don't handle panics
 | 
						|
	runtime.ReallyCrash = true
 | 
						|
 | 
						|
	// TCP setup.
 | 
						|
	tcp := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
						|
		w.WriteHeader(http.StatusOK)
 | 
						|
		w.Write([]byte(r.URL.Path[1:]))
 | 
						|
	}))
 | 
						|
	defer tcp.Close()
 | 
						|
 | 
						|
	u, err := url.Parse(tcp.URL)
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to parse: %v", err))
 | 
						|
	}
 | 
						|
	_, port, err := net.SplitHostPort(u.Host)
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to parse: %v", err))
 | 
						|
	}
 | 
						|
	tcpServerPortValue, err := strconv.Atoi(port)
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to atoi(%s): %v", port, err))
 | 
						|
	}
 | 
						|
	tcpServerPort = int32(tcpServerPortValue)
 | 
						|
 | 
						|
	// UDP setup.
 | 
						|
	udp, err := newUDPEchoServer()
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to make a UDP server: %v", err))
 | 
						|
	}
 | 
						|
	_, port, err = net.SplitHostPort(udp.LocalAddr().String())
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to parse: %v", err))
 | 
						|
	}
 | 
						|
	udpServerPortValue, err := strconv.Atoi(port)
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to atoi(%s): %v", port, err))
 | 
						|
	}
 | 
						|
	udpServerPort = int32(udpServerPortValue)
 | 
						|
	go udp.Loop()
 | 
						|
 | 
						|
	ret := m.Run()
 | 
						|
	// it should be safe to call Close() multiple times.
 | 
						|
	tcp.Close()
 | 
						|
	os.Exit(ret)
 | 
						|
}
 | 
						|
 | 
						|
func testEchoTCP(t *testing.T, address string, port int) {
 | 
						|
	path := "aaaaa"
 | 
						|
	res, err := http.Get("http://" + address + ":" + fmt.Sprintf("%d", port) + "/" + path)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to server: %v", err)
 | 
						|
	}
 | 
						|
	defer res.Body.Close()
 | 
						|
	data, err := ioutil.ReadAll(res.Body)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("error reading data: %v %v", err, string(data))
 | 
						|
	}
 | 
						|
	if string(data) != path {
 | 
						|
		t.Errorf("expected: %s, got %s", path, string(data))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testEchoUDP(t *testing.T, address string, port int) {
 | 
						|
	data := "abc123"
 | 
						|
 | 
						|
	conn, err := net.Dial("udp", joinHostPort(address, port))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to server: %v", err)
 | 
						|
	}
 | 
						|
	if _, err := conn.Write([]byte(data)); err != nil {
 | 
						|
		t.Fatalf("error sending to server: %v", err)
 | 
						|
	}
 | 
						|
	var resp [1024]byte
 | 
						|
	n, err := conn.Read(resp[0:])
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("error receiving data: %v", err)
 | 
						|
	}
 | 
						|
	if string(resp[0:n]) != data {
 | 
						|
		t.Errorf("expected: %s, got %s", data, string(resp[0:n]))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func waitForNumProxyLoops(t *testing.T, p *Proxier, want int32) {
 | 
						|
	var got int32
 | 
						|
	for i := 0; i < 600; i++ {
 | 
						|
		got = atomic.LoadInt32(&p.numProxyLoops)
 | 
						|
		if got == want {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		time.Sleep(100 * time.Millisecond)
 | 
						|
	}
 | 
						|
	t.Errorf("expected %d ProxyLoops running, got %d", want, got)
 | 
						|
}
 | 
						|
 | 
						|
func waitForNumProxyClients(t *testing.T, s *serviceInfo, want int, timeout time.Duration) {
 | 
						|
	var got int
 | 
						|
	now := time.Now()
 | 
						|
	deadline := now.Add(timeout)
 | 
						|
	for time.Now().Before(deadline) {
 | 
						|
		s.activeClients.mu.Lock()
 | 
						|
		got = len(s.activeClients.clients)
 | 
						|
		s.activeClients.mu.Unlock()
 | 
						|
		if got == want {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		time.Sleep(500 * time.Millisecond)
 | 
						|
	}
 | 
						|
	t.Errorf("expected %d ProxyClients live, got %d", want, got)
 | 
						|
}
 | 
						|
 | 
						|
func getPortNum(t *testing.T, addr string) int {
 | 
						|
	_, portStr, err := net.SplitHostPort(addr)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("error getting port from %s", addr)
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
	portNum, err := strconv.Atoi(portStr)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("error getting port from %s", addr)
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
 | 
						|
	return portNum
 | 
						|
}
 | 
						|
 | 
						|
func TestTCPProxy(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestUDPProxy(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoUDP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestUDPProxyTimeout(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
	testEchoUDP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	// When connecting to a UDP service endpoint, there should be a Conn for proxy.
 | 
						|
	waitForNumProxyClients(t, svcInfo, 1, time.Second)
 | 
						|
	// If conn has no activity for serviceInfo.timeout since last Read/Write, it should be closed because of timeout.
 | 
						|
	waitForNumProxyClients(t, svcInfo, 0, 2*time.Second)
 | 
						|
}
 | 
						|
 | 
						|
func TestMultiPortProxy(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	serviceP := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo-p"}, Port: "p"}
 | 
						|
	serviceQ := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo-q"}, Port: "q"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: serviceP.Name, Namespace: serviceP.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Protocol: "TCP", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: serviceQ.Name, Namespace: serviceQ.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "q", Protocol: "UDP", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalNameP := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: serviceP.Namespace, Name: serviceP.Name}, Port: serviceP.Port, PortalIPName: listenIP}
 | 
						|
	svcInfoP, err := p.addServicePortPortal(servicePortPortalNameP, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfoP.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	servicePortPortalNameQ := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: serviceQ.Namespace, Name: serviceQ.Name}, Port: serviceQ.Port, PortalIPName: listenIP}
 | 
						|
	svcInfoQ, err := p.addServicePortPortal(servicePortPortalNameQ, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoUDP(t, "127.0.0.1", getPortNum(t, svcInfoQ.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 2)
 | 
						|
}
 | 
						|
 | 
						|
func TestMultiPortOnServiceAdd(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"}
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	p.OnServiceAdd(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: serviceP.Name, Namespace: serviceP.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: "0.0.0.0", Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     0,
 | 
						|
			Protocol: "TCP",
 | 
						|
		}, {
 | 
						|
			Name:     "q",
 | 
						|
			Port:     0,
 | 
						|
			Protocol: "UDP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	waitForNumProxyLoops(t, p, 2)
 | 
						|
 | 
						|
	servicePortPortalNameP := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: serviceP.Namespace, Name: serviceP.Name}, Port: serviceP.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, exists := p.getServiceInfo(servicePortPortalNameP)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalNameP)
 | 
						|
	}
 | 
						|
	if svcInfo.portal.ip != "0.0.0.0" || svcInfo.portal.port != 0 || svcInfo.protocol != "TCP" {
 | 
						|
		t.Errorf("unexpected serviceInfo for %s: %#v", serviceP, svcInfo)
 | 
						|
	}
 | 
						|
 | 
						|
	servicePortPortalNameQ := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: serviceQ.Namespace, Name: serviceQ.Name}, Port: serviceQ.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, exists = p.getServiceInfo(servicePortPortalNameQ)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalNameQ)
 | 
						|
	}
 | 
						|
	if svcInfo.portal.ip != "0.0.0.0" || svcInfo.portal.port != 0 || svcInfo.protocol != "UDP" {
 | 
						|
		t.Errorf("unexpected serviceInfo for %s: %#v", serviceQ, svcInfo)
 | 
						|
	}
 | 
						|
 | 
						|
	servicePortPortalNameX := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: serviceX.Namespace, Name: serviceX.Name}, Port: serviceX.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, exists = p.getServiceInfo(servicePortPortalNameX)
 | 
						|
	if exists {
 | 
						|
		t.Fatalf("found unwanted serviceInfo for %s: %#v", serviceX, svcInfo)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Helper: Stops the proxy for the named service.
 | 
						|
func stopProxyByName(proxier *Proxier, service ServicePortPortalName) error {
 | 
						|
	info, found := proxier.getServiceInfo(service)
 | 
						|
	if !found {
 | 
						|
		return fmt.Errorf("unknown service: %s", service)
 | 
						|
	}
 | 
						|
	return proxier.stopProxy(service, info)
 | 
						|
}
 | 
						|
 | 
						|
func TestTCPProxyStop(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Namespace: service.Namespace, Name: service.Name},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 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("", getPortNum(t, svcInfo.socket.Addr().String())))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to proxy: %v", err)
 | 
						|
	}
 | 
						|
	conn.Close()
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	stopProxyByName(p, servicePortPortalName)
 | 
						|
	if svcInfo.isAlive() {
 | 
						|
		t.Fatalf("wrong value for isAlive(): expected false")
 | 
						|
	}
 | 
						|
	// Wait for the port to really close.
 | 
						|
	if err := waitForClosedPortTCP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
}
 | 
						|
 | 
						|
func TestUDPProxyStop(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Namespace: service.Namespace, Name: service.Name},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	conn, err := net.Dial("udp", joinHostPort("", getPortNum(t, svcInfo.socket.Addr().String())))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to proxy: %v", err)
 | 
						|
	}
 | 
						|
	conn.Close()
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	stopProxyByName(p, servicePortPortalName)
 | 
						|
	// Wait for the port to really close.
 | 
						|
	if err := waitForClosedPortUDP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
}
 | 
						|
 | 
						|
func TestTCPProxyUpdateDelete(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Namespace: service.Namespace, Name: service.Name},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	fmt.Println("here0")
 | 
						|
	conn, err := net.Dial("tcp", joinHostPort("", getPortNum(t, svcInfo.socket.Addr().String())))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to proxy: %v", err)
 | 
						|
	}
 | 
						|
	conn.Close()
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceDelete(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	if err := waitForClosedPortTCP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
}
 | 
						|
 | 
						|
func TestUDPProxyUpdateDelete(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Namespace: service.Namespace, Name: service.Name},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	conn, err := net.Dial("udp", joinHostPort("", getPortNum(t, svcInfo.socket.Addr().String())))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to proxy: %v", err)
 | 
						|
	}
 | 
						|
	conn.Close()
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceDelete(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "UDP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	if err := waitForClosedPortUDP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
}
 | 
						|
 | 
						|
func TestTCPProxyUpdateDeleteUpdate(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	endpoint := &v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	}
 | 
						|
	lb.OnEndpointsAdd(endpoint)
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	conn, err := net.Dial("tcp", joinHostPort("", getPortNum(t, svcInfo.socket.Addr().String())))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to proxy: %v", err)
 | 
						|
	}
 | 
						|
	conn.Close()
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceDelete(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	if err := waitForClosedPortTCP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	// need to add endpoint here because it got clean up during service delete
 | 
						|
	lb.OnEndpointsAdd(endpoint)
 | 
						|
	p.OnServiceAdd(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	svcInfo, exists := p.getServiceInfo(servicePortPortalName)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalName)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestUDPProxyUpdateDeleteUpdate(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	endpoint := &v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	}
 | 
						|
	lb.OnEndpointsAdd(endpoint)
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	conn, err := net.Dial("udp", joinHostPort("", getPortNum(t, svcInfo.socket.Addr().String())))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error connecting to proxy: %v", err)
 | 
						|
	}
 | 
						|
	conn.Close()
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceDelete(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "UDP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	if err := waitForClosedPortUDP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	// need to add endpoint here because it got clean up during service delete
 | 
						|
	lb.OnEndpointsAdd(endpoint)
 | 
						|
	p.OnServiceAdd(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "UDP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	svcInfo, exists := p.getServiceInfo(servicePortPortalName)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalName)
 | 
						|
	}
 | 
						|
	testEchoUDP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestTCPProxyUpdatePort(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceAdd(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     0,
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	// Wait for the socket to actually get free.
 | 
						|
	if err := waitForClosedPortTCP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	svcInfo, exists := p.getServiceInfo(servicePortPortalName)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalName)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	// This is a bit async, but this should be sufficient.
 | 
						|
	time.Sleep(500 * time.Millisecond)
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestUDPProxyUpdatePort(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: udpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "UDP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceAdd(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     0,
 | 
						|
			Protocol: "UDP",
 | 
						|
		}}},
 | 
						|
	})
 | 
						|
	// Wait for the socket to actually get free.
 | 
						|
	if err := waitForClosedPortUDP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	svcInfo, exists := p.getServiceInfo(servicePortPortalName)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalName)
 | 
						|
	}
 | 
						|
	testEchoUDP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestProxyUpdatePublicIPs(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	lb.OnEndpointsAdd(&v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	})
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	p.OnServiceAdd(&v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{
 | 
						|
			Ports: []v1.ServicePort{{
 | 
						|
				Name:     "p",
 | 
						|
				Port:     int32(svcInfo.portal.port),
 | 
						|
				Protocol: "TCP",
 | 
						|
			}},
 | 
						|
			ClusterIP:   svcInfo.portal.ip,
 | 
						|
			ExternalIPs: []string{"0.0.0.0"},
 | 
						|
		},
 | 
						|
	})
 | 
						|
	// Wait for the socket to actually get free.
 | 
						|
	if err := waitForClosedPortTCP(p, getPortNum(t, svcInfo.socket.Addr().String())); err != nil {
 | 
						|
		t.Fatalf(err.Error())
 | 
						|
	}
 | 
						|
	svcInfo, exists := p.getServiceInfo(servicePortPortalName)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("can't find serviceInfo for %s", servicePortPortalName)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	// This is a bit async, but this should be sufficient.
 | 
						|
	time.Sleep(500 * time.Millisecond)
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestProxyUpdatePortal(t *testing.T) {
 | 
						|
	lb := NewLoadBalancerRR()
 | 
						|
	service := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: "testnamespace", Name: "echo"}, Port: "p"}
 | 
						|
	endpoint := &v1.Endpoints{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Subsets: []v1.EndpointSubset{{
 | 
						|
			Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
 | 
						|
			Ports:     []v1.EndpointPort{{Name: "p", Port: tcpServerPort}},
 | 
						|
		}},
 | 
						|
	}
 | 
						|
	lb.OnEndpointsAdd(endpoint)
 | 
						|
 | 
						|
	listenIP := "0.0.0.0"
 | 
						|
	p, err := createProxier(lb, net.ParseIP(listenIP), netshtest.NewFake(), net.ParseIP("127.0.0.1"), time.Minute, udpIdleTimeoutForTest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	waitForNumProxyLoops(t, p, 0)
 | 
						|
 | 
						|
	servicePortPortalName := ServicePortPortalName{NamespacedName: types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, Port: service.Port, PortalIPName: listenIP}
 | 
						|
	svcInfo, err := p.addServicePortPortal(servicePortPortalName, "TCP", listenIP, 0, time.Second)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("error adding new service: %#v", err)
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
 | 
						|
	svcv0 := &v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(svcInfo.portal.port),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	}
 | 
						|
 | 
						|
	svcv1 := &v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: "", Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(svcInfo.portal.port),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	}
 | 
						|
 | 
						|
	p.OnServiceUpdate(svcv0, svcv1)
 | 
						|
	_, exists := p.getServiceInfo(servicePortPortalName)
 | 
						|
	if exists {
 | 
						|
		t.Fatalf("service with empty ClusterIP should not be included in the proxy")
 | 
						|
	}
 | 
						|
 | 
						|
	svcv2 := &v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: "None", Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(getPortNum(t, svcInfo.socket.Addr().String())),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	}
 | 
						|
	p.OnServiceUpdate(svcv1, svcv2)
 | 
						|
	_, exists = p.getServiceInfo(servicePortPortalName)
 | 
						|
	if exists {
 | 
						|
		t.Fatalf("service with 'None' as ClusterIP should not be included in the proxy")
 | 
						|
	}
 | 
						|
 | 
						|
	svcv3 := &v1.Service{
 | 
						|
		ObjectMeta: metav1.ObjectMeta{Name: service.Name, Namespace: service.Namespace},
 | 
						|
		Spec: v1.ServiceSpec{ClusterIP: listenIP, Ports: []v1.ServicePort{{
 | 
						|
			Name:     "p",
 | 
						|
			Port:     int32(svcInfo.portal.port),
 | 
						|
			Protocol: "TCP",
 | 
						|
		}}},
 | 
						|
	}
 | 
						|
	p.OnServiceUpdate(svcv2, svcv3)
 | 
						|
	lb.OnEndpointsAdd(endpoint)
 | 
						|
	svcInfo, exists = p.getServiceInfo(servicePortPortalName)
 | 
						|
	if !exists {
 | 
						|
		t.Fatalf("service with ClusterIP set not found in the proxy")
 | 
						|
	}
 | 
						|
	testEchoTCP(t, "127.0.0.1", getPortNum(t, svcInfo.socket.Addr().String()))
 | 
						|
	waitForNumProxyLoops(t, p, 1)
 | 
						|
}
 | 
						|
 | 
						|
func TestNoopEndpointSlice(t *testing.T) {
 | 
						|
	p := Proxier{}
 | 
						|
	p.OnEndpointSliceAdd(&discovery.EndpointSlice{})
 | 
						|
	p.OnEndpointSliceUpdate(&discovery.EndpointSlice{}, &discovery.EndpointSlice{})
 | 
						|
	p.OnEndpointSliceDelete(&discovery.EndpointSlice{})
 | 
						|
	p.OnEndpointSlicesSynced()
 | 
						|
}
 | 
						|
 | 
						|
// TODO(justinsb): Add test for nodePort conflict detection, once we have nodePort wired in
 |