2014-06-06 23:40:48 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2014-06-06 23:40:48 +00:00
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 .
* /
2015-08-08 00:07:15 +00:00
package userspace
2014-06-06 23:40:48 +00:00
import (
"fmt"
2014-08-13 21:07:14 +00:00
"io/ioutil"
2014-06-06 23:40:48 +00:00
"net"
2014-08-13 21:07:14 +00:00
"net/http"
"net/http/httptest"
"net/url"
2016-04-30 15:34:30 +00:00
"os"
2019-03-29 14:25:21 +00:00
"reflect"
2015-02-19 03:54:15 +00:00
"strconv"
2015-02-03 22:37:41 +00:00
"sync/atomic"
2014-06-06 23:40:48 +00:00
"testing"
2014-07-30 13:52:03 +00:00
"time"
2014-06-06 23:40:48 +00:00
2018-08-15 13:51:19 +00:00
"k8s.io/api/core/v1"
2017-01-17 03:38:19 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime"
2019-03-29 14:25:21 +00:00
"k8s.io/apimachinery/pkg/util/wait"
2015-08-08 00:07:15 +00:00
"k8s.io/kubernetes/pkg/proxy"
2015-10-27 06:08:37 +00:00
ipttest "k8s.io/kubernetes/pkg/util/iptables/testing"
2017-07-19 05:58:53 +00:00
"k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
2014-06-06 23:40:48 +00:00
)
2015-10-16 21:52:58 +00:00
const (
udpIdleTimeoutForTest = 250 * time . Millisecond
)
2014-09-18 23:03:34 +00:00
func joinHostPort ( host string , port int ) string {
return net . JoinHostPort ( host , fmt . Sprintf ( "%d" , port ) )
}
func waitForClosedPortTCP ( p * Proxier , proxyPort int ) error {
2014-08-04 19:35:03 +00:00
for i := 0 ; i < 50 ; i ++ {
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "tcp" , joinHostPort ( "" , proxyPort ) )
2014-08-04 19:35:03 +00:00
if err != nil {
return nil
}
2014-09-11 16:00:06 +00:00
conn . Close ( )
time . Sleep ( 1 * time . Millisecond )
}
2014-09-18 23:03:34 +00:00
return fmt . Errorf ( "port %d still open" , proxyPort )
2014-09-11 16:00:06 +00:00
}
2014-09-18 23:03:34 +00:00
func waitForClosedPortUDP ( p * Proxier , proxyPort int ) error {
2014-09-11 16:00:06 +00:00
for i := 0 ; i < 50 ; i ++ {
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "udp" , joinHostPort ( "" , proxyPort ) )
2014-09-11 16:00:06 +00:00
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 ( )
2014-08-04 19:35:03 +00:00
time . Sleep ( 1 * time . Millisecond )
}
2014-09-18 23:03:34 +00:00
return fmt . Errorf ( "port %d still open" , proxyPort )
}
2019-03-29 14:25:21 +00:00
func waitForServiceInfo ( p * Proxier , service proxy . ServicePortName ) ( * ServiceInfo , bool ) {
var svcInfo * ServiceInfo
var exists bool
wait . PollImmediate ( 50 * time . Millisecond , 3 * time . Second , func ( ) ( bool , error ) {
svcInfo , exists = p . getServiceInfo ( service )
return exists , nil
} )
return svcInfo , exists
}
2018-03-09 01:22:30 +00:00
// 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 )
}
}
2016-04-27 04:35:14 +00:00
var tcpServerPort int32
var udpServerPort int32
2014-08-13 21:07:14 +00:00
2016-04-30 15:34:30 +00:00
func TestMain ( m * testing . M ) {
2014-11-11 06:18:01 +00:00
// Don't handle panics
2016-01-15 07:32:10 +00:00
runtime . ReallyCrash = true
2014-11-11 06:18:01 +00:00
2014-09-11 16:00:06 +00:00
// TCP setup.
tcp := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
2014-08-13 21:07:14 +00:00
w . WriteHeader ( http . StatusOK )
w . Write ( [ ] byte ( r . URL . Path [ 1 : ] ) )
} ) )
2016-04-30 15:34:30 +00:00
defer tcp . Close ( )
2014-09-11 16:00:06 +00:00
u , err := url . Parse ( tcp . URL )
2014-06-06 23:40:48 +00:00
if err != nil {
2014-08-13 21:07:14 +00:00
panic ( fmt . Sprintf ( "failed to parse: %v" , err ) )
}
2015-02-19 03:54:15 +00:00
_ , port , err := net . SplitHostPort ( u . Host )
2014-08-13 21:07:14 +00:00
if err != nil {
panic ( fmt . Sprintf ( "failed to parse: %v" , err ) )
2014-06-06 23:40:48 +00:00
}
2016-04-27 04:35:14 +00:00
tcpServerPortValue , err := strconv . Atoi ( port )
2015-02-19 03:54:15 +00:00
if err != nil {
panic ( fmt . Sprintf ( "failed to atoi(%s): %v" , port , err ) )
}
2016-04-27 04:35:14 +00:00
tcpServerPort = int32 ( tcpServerPortValue )
2014-09-11 16:00:06 +00:00
// UDP setup.
udp , err := newUDPEchoServer ( )
if err != nil {
panic ( fmt . Sprintf ( "failed to make a UDP server: %v" , err ) )
}
2015-02-19 03:54:15 +00:00
_ , port , err = net . SplitHostPort ( udp . LocalAddr ( ) . String ( ) )
2014-09-11 16:00:06 +00:00
if err != nil {
panic ( fmt . Sprintf ( "failed to parse: %v" , err ) )
}
2016-04-27 04:35:14 +00:00
udpServerPortValue , err := strconv . Atoi ( port )
2015-02-19 03:54:15 +00:00
if err != nil {
panic ( fmt . Sprintf ( "failed to atoi(%s): %v" , port , err ) )
}
2016-04-27 04:35:14 +00:00
udpServerPort = int32 ( udpServerPortValue )
2014-09-11 16:00:06 +00:00
go udp . Loop ( )
2016-04-30 15:34:30 +00:00
ret := m . Run ( )
// it should be safe to call Close() multiple times.
tcp . Close ( )
os . Exit ( ret )
2014-06-13 00:18:19 +00:00
}
2014-09-18 23:03:34 +00:00
func testEchoTCP ( t * testing . T , address string , port int ) {
2014-08-13 21:07:14 +00:00
path := "aaaaa"
2014-09-18 23:03:34 +00:00
res , err := http . Get ( "http://" + address + ":" + fmt . Sprintf ( "%d" , port ) + "/" + path )
2014-07-30 13:52:03 +00:00
if err != nil {
2014-08-13 21:07:14 +00:00
t . Fatalf ( "error connecting to server: %v" , err )
2014-07-30 13:52:03 +00:00
}
2014-08-13 21:07:14 +00:00
defer res . Body . Close ( )
data , err := ioutil . ReadAll ( res . Body )
if err != nil {
t . Errorf ( "error reading data: %v %v" , err , string ( data ) )
2014-07-30 13:52:03 +00:00
}
2014-08-13 21:07:14 +00:00
if string ( data ) != path {
t . Errorf ( "expected: %s, got %s" , path , string ( data ) )
2014-07-30 13:52:03 +00:00
}
}
2014-09-18 23:03:34 +00:00
func testEchoUDP ( t * testing . T , address string , port int ) {
2014-09-11 16:00:06 +00:00
data := "abc123"
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "udp" , joinHostPort ( address , port ) )
2014-09-11 16:00:06 +00:00
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 ] ) )
}
}
2015-02-03 22:37:41 +00:00
func waitForNumProxyLoops ( t * testing . T , p * Proxier , want int32 ) {
var got int32
2015-09-01 23:08:13 +00:00
for i := 0 ; i < 600 ; i ++ {
2015-02-03 22:37:41 +00:00
got = atomic . LoadInt32 ( & p . numProxyLoops )
if got == want {
return
}
2015-09-01 23:08:13 +00:00
time . Sleep ( 100 * time . Millisecond )
2015-02-03 22:37:41 +00:00
}
t . Errorf ( "expected %d ProxyLoops running, got %d" , want , got )
}
2016-08-18 17:59:09 +00:00
func waitForNumProxyClients ( t * testing . T , s * ServiceInfo , want int , timeout time . Duration ) {
2015-08-19 13:50:43 +00:00
var got int
now := time . Now ( )
deadline := now . Add ( timeout )
for time . Now ( ) . Before ( deadline ) {
2016-08-18 17:59:09 +00:00
s . ActiveClients . Mu . Lock ( )
got = len ( s . ActiveClients . Clients )
s . ActiveClients . Mu . Unlock ( )
2015-08-19 13:50:43 +00:00
if got == want {
return
}
time . Sleep ( 500 * time . Millisecond )
}
t . Errorf ( "expected %d ProxyClients live, got %d" , want , got )
}
2019-03-29 14:25:21 +00:00
func startProxier ( p * Proxier , t * testing . T ) {
go func ( ) {
p . SyncLoop ( )
} ( )
waitForNumProxyLoops ( t , p , 0 )
p . OnServiceSynced ( )
p . OnEndpointsSynced ( )
}
2014-09-10 20:44:20 +00:00
func TestTCPProxy ( t * testing . T ) {
2014-06-06 23:40:48 +00:00
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-10 20:44:20 +00:00
} )
2014-06-06 23:40:48 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-06-13 00:18:19 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "TCP" , 0 , time . Second )
2014-07-30 13:52:03 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2014-09-18 23:03:34 +00:00
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-07-30 13:52:03 +00:00
}
2014-09-11 16:00:06 +00:00
func TestUDPProxy ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : udpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-11 16:00:06 +00:00
} )
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-09-11 16:00:06 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "UDP" , 0 , time . Second )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2014-09-18 23:03:34 +00:00
testEchoUDP ( t , "127.0.0.1" , svcInfo . proxyPort )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
}
2015-08-19 13:50:43 +00:00
func TestUDPProxyTimeout ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : udpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2015-08-19 13:50:43 +00:00
} )
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-08-19 13:50:43 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2015-08-19 13:50:43 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "UDP" , 0 , time . Second )
2015-08-19 13:50:43 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
waitForNumProxyLoops ( t , p , 1 )
testEchoUDP ( t , "127.0.0.1" , svcInfo . proxyPort )
2016-06-22 09:40:52 +00:00
// When connecting to a UDP service endpoint, there should be a Conn for proxy.
2015-08-19 13:50:43 +00:00
waitForNumProxyClients ( t , svcInfo , 1 , time . Second )
2016-06-22 09:40:52 +00:00
// If conn has no activity for serviceInfo.timeout since last Read/Write, it should be closed because of timeout.
2015-08-19 13:50:43 +00:00
waitForNumProxyClients ( t , svcInfo , 0 , 2 * time . Second )
}
2015-03-13 15:16:41 +00:00
func TestMultiPortProxy ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
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" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : serviceP . Name , Namespace : serviceP . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Protocol : "TCP" , Port : tcpServerPort } } ,
2015-03-13 15:16:41 +00:00
} } ,
2017-03-20 13:02:35 +00:00
} )
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : serviceQ . Name , Namespace : serviceQ . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "q" , Protocol : "UDP" , Port : udpServerPort } } ,
2015-03-13 15:16:41 +00:00
} } ,
2017-03-20 13:02:35 +00:00
} )
2015-03-13 15:16:41 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2015-03-13 15:16:41 +00:00
2017-05-02 11:43:42 +00:00
svcInfoP , err := p . addServiceOnPort ( serviceP , "TCP" , 0 , time . Second )
2015-03-13 15:16:41 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
testEchoTCP ( t , "127.0.0.1" , svcInfoP . proxyPort )
waitForNumProxyLoops ( t , p , 1 )
2017-05-02 11:43:42 +00:00
svcInfoQ , err := p . addServiceOnPort ( serviceQ , "UDP" , 0 , time . Second )
2015-03-13 15:16:41 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
testEchoUDP ( t , "127.0.0.1" , svcInfoQ . proxyPort )
waitForNumProxyLoops ( t , p , 2 )
}
2017-05-04 13:28:15 +00:00
func TestMultiPortOnServiceAdd ( t * testing . T ) {
2015-03-13 15:16:41 +00:00
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
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" }
2015-03-13 15:16:41 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2015-03-13 15:16:41 +00:00
2018-08-15 13:51:19 +00:00
p . OnServiceAdd ( & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : serviceP . Name , Namespace : serviceP . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
Port : 80 ,
Protocol : "TCP" ,
} , {
Name : "q" ,
Port : 81 ,
Protocol : "UDP" ,
} } } ,
2017-05-04 13:28:15 +00:00
} )
2015-03-13 15:16:41 +00:00
waitForNumProxyLoops ( t , p , 2 )
2019-03-29 14:25:21 +00:00
svcInfo , exists := waitForServiceInfo ( p , serviceP )
2015-03-13 15:16:41 +00:00
if ! exists {
t . Fatalf ( "can't find serviceInfo for %s" , serviceP )
}
2015-05-23 20:41:11 +00:00
if svcInfo . portal . ip . String ( ) != "1.2.3.4" || svcInfo . portal . port != 80 || svcInfo . protocol != "TCP" {
2015-03-13 15:16:41 +00:00
t . Errorf ( "unexpected serviceInfo for %s: %#v" , serviceP , svcInfo )
}
2019-03-29 14:25:21 +00:00
svcInfo , exists = waitForServiceInfo ( p , serviceQ )
2015-03-13 15:16:41 +00:00
if ! exists {
t . Fatalf ( "can't find serviceInfo for %s" , serviceQ )
}
2015-05-23 20:41:11 +00:00
if svcInfo . portal . ip . String ( ) != "1.2.3.4" || svcInfo . portal . port != 81 || svcInfo . protocol != "UDP" {
2015-03-13 15:16:41 +00:00
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 )
}
}
2014-09-20 18:38:05 +00:00
// Helper: Stops the proxy for the named service.
2015-08-08 00:07:15 +00:00
func stopProxyByName ( proxier * Proxier , service proxy . ServicePortName ) error {
2019-03-29 14:25:21 +00:00
proxier . mu . Lock ( )
defer proxier . mu . Unlock ( )
info , found := proxier . serviceMap [ service ]
2014-09-20 18:38:05 +00:00
if ! found {
return fmt . Errorf ( "unknown service: %s" , service )
}
return proxier . stopProxy ( service , info )
}
2014-09-10 20:44:20 +00:00
func TestTCPProxyStop ( t * testing . T ) {
2014-07-30 13:52:03 +00:00
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Namespace : service . Namespace , Name : service . Name } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-10 20:44:20 +00:00
} )
2014-07-30 13:52:03 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-07-30 13:52:03 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "TCP" , 0 , time . Second )
2014-06-13 00:18:19 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
2014-06-06 23:40:48 +00:00
}
2016-08-18 17:59:09 +00:00
if ! svcInfo . IsAlive ( ) {
t . Fatalf ( "wrong value for IsAlive(): expected true" )
2015-09-01 23:40:11 +00:00
}
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "tcp" , joinHostPort ( "" , svcInfo . proxyPort ) )
2014-06-06 23:40:48 +00:00
if err != nil {
t . Fatalf ( "error connecting to proxy: %v" , err )
}
2014-07-30 13:52:03 +00:00
conn . Close ( )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-07-30 13:52:03 +00:00
2015-02-18 19:30:18 +00:00
stopProxyByName ( p , service )
2016-08-18 17:59:09 +00:00
if svcInfo . IsAlive ( ) {
t . Fatalf ( "wrong value for IsAlive(): expected false" )
2015-09-01 23:40:11 +00:00
}
2014-07-30 13:56:42 +00:00
// Wait for the port to really close.
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortTCP ( p , svcInfo . proxyPort ) ; err != nil {
2014-08-04 19:35:03 +00:00
t . Fatalf ( err . Error ( ) )
2014-07-29 12:15:43 +00:00
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 0 )
2014-07-30 13:52:03 +00:00
}
2014-09-11 16:00:06 +00:00
func TestUDPProxyStop ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Namespace : service . Namespace , Name : service . Name } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : udpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-11 16:00:06 +00:00
} )
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-09-11 16:00:06 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "UDP" , 0 , time . Second )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "udp" , joinHostPort ( "" , svcInfo . proxyPort ) )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error connecting to proxy: %v" , err )
}
conn . Close ( )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
2015-02-18 19:30:18 +00:00
stopProxyByName ( p , service )
2014-09-11 16:00:06 +00:00
// Wait for the port to really close.
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortUDP ( p , svcInfo . proxyPort ) ; err != nil {
2014-09-11 16:00:06 +00:00
t . Fatalf ( err . Error ( ) )
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 0 )
2014-09-11 16:00:06 +00:00
}
2014-09-10 20:44:20 +00:00
func TestTCPProxyUpdateDelete ( t * testing . T ) {
2014-07-30 13:52:03 +00:00
lb := NewLoadBalancerRR ( )
2019-03-29 14:25:21 +00:00
servicePortName := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2019-03-29 14:25:21 +00:00
ObjectMeta : metav1 . ObjectMeta { Namespace : servicePortName . Namespace , Name : servicePortName . Name } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-10 20:44:20 +00:00
} )
2014-07-30 13:52:03 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-07-30 13:52:03 +00:00
2019-03-29 14:25:21 +00:00
service := & v1 . Service {
ObjectMeta : metav1 . ObjectMeta { Name : servicePortName . Name , Namespace : servicePortName . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2017-05-04 13:28:15 +00:00
Name : "p" ,
2019-03-29 14:25:21 +00:00
Port : 9997 ,
2017-05-04 13:28:15 +00:00
Protocol : "TCP" ,
} } } ,
2019-03-29 14:25:21 +00:00
}
p . OnServiceAdd ( service )
waitForNumProxyLoops ( t , p , 1 )
p . OnServiceDelete ( service )
if err := waitForClosedPortTCP ( p , int ( service . Spec . Ports [ 0 ] . Port ) ) ; err != nil {
2014-08-04 19:35:03 +00:00
t . Fatalf ( err . Error ( ) )
2014-07-30 13:52:03 +00:00
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 0 )
2014-07-30 13:52:03 +00:00
}
2014-09-11 16:00:06 +00:00
func TestUDPProxyUpdateDelete ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Namespace : service . Namespace , Name : service . Name } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : udpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-11 16:00:06 +00:00
} )
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-09-11 16:00:06 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "UDP" , 0 , time . Second )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "udp" , joinHostPort ( "" , svcInfo . proxyPort ) )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error connecting to proxy: %v" , err )
}
conn . Close ( )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
2018-08-15 13:51:19 +00:00
p . OnServiceDelete ( & v1 . Service {
2017-05-04 13:28:15 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2017-05-04 13:28:15 +00:00
Name : "p" ,
Port : int32 ( svcInfo . proxyPort ) ,
Protocol : "UDP" ,
} } } ,
} )
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortUDP ( p , svcInfo . proxyPort ) ; err != nil {
2014-09-11 16:00:06 +00:00
t . Fatalf ( err . Error ( ) )
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 0 )
2014-09-11 16:00:06 +00:00
}
2014-09-10 20:44:20 +00:00
func TestTCPProxyUpdateDeleteUpdate ( t * testing . T ) {
2014-08-19 19:24:10 +00:00
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
endpoint := & v1 . Endpoints {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2016-07-08 00:43:22 +00:00
} } ,
}
2017-03-20 13:02:35 +00:00
lb . OnEndpointsAdd ( endpoint )
2014-08-19 19:24:10 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-08-19 19:24:10 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "TCP" , 0 , time . Second )
2014-08-19 19:24:10 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "tcp" , joinHostPort ( "" , svcInfo . proxyPort ) )
2014-08-19 19:24:10 +00:00
if err != nil {
t . Fatalf ( "error connecting to proxy: %v" , err )
}
conn . Close ( )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-08-19 19:24:10 +00:00
2018-08-15 13:51:19 +00:00
p . OnServiceDelete ( & v1 . Service {
2017-05-04 13:28:15 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2017-05-04 13:28:15 +00:00
Name : "p" ,
Port : int32 ( svcInfo . proxyPort ) ,
Protocol : "TCP" ,
} } } ,
} )
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortTCP ( p , svcInfo . proxyPort ) ; err != nil {
2014-08-19 19:24:10 +00:00
t . Fatalf ( err . Error ( ) )
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 0 )
2015-03-13 15:16:41 +00:00
2016-07-08 00:43:22 +00:00
// need to add endpoint here because it got clean up during service delete
2017-03-20 13:02:35 +00:00
lb . OnEndpointsAdd ( endpoint )
2018-08-15 13:51:19 +00:00
p . OnServiceAdd ( & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
2016-04-27 04:35:14 +00:00
Port : int32 ( svcInfo . proxyPort ) ,
2015-03-13 15:16:41 +00:00
Protocol : "TCP" ,
} } } ,
2017-05-04 13:28:15 +00:00
} )
2019-03-29 14:25:21 +00:00
svcInfo , exists := waitForServiceInfo ( p , service )
2015-02-04 06:45:00 +00:00
if ! exists {
2015-02-18 19:30:18 +00:00
t . Fatalf ( "can't find serviceInfo for %s" , service )
2015-02-04 06:45:00 +00:00
}
2014-09-18 23:03:34 +00:00
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-08-19 19:24:10 +00:00
}
2014-09-11 16:00:06 +00:00
func TestUDPProxyUpdateDeleteUpdate ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
endpoint := & v1 . Endpoints {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : udpServerPort } } ,
2016-07-08 00:43:22 +00:00
} } ,
}
2017-03-20 13:02:35 +00:00
lb . OnEndpointsAdd ( endpoint )
2014-09-11 16:00:06 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-09-11 16:00:06 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "UDP" , 0 , time . Second )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2014-09-18 23:03:34 +00:00
conn , err := net . Dial ( "udp" , joinHostPort ( "" , svcInfo . proxyPort ) )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error connecting to proxy: %v" , err )
}
conn . Close ( )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
2018-08-15 13:51:19 +00:00
p . OnServiceDelete ( & v1 . Service {
2017-05-04 13:28:15 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2017-05-04 13:28:15 +00:00
Name : "p" ,
Port : int32 ( svcInfo . proxyPort ) ,
Protocol : "UDP" ,
} } } ,
} )
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortUDP ( p , svcInfo . proxyPort ) ; err != nil {
2014-09-11 16:00:06 +00:00
t . Fatalf ( err . Error ( ) )
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 0 )
2015-03-13 15:16:41 +00:00
2016-07-08 00:43:22 +00:00
// need to add endpoint here because it got clean up during service delete
2017-03-20 13:02:35 +00:00
lb . OnEndpointsAdd ( endpoint )
2018-08-15 13:51:19 +00:00
p . OnServiceAdd ( & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
2016-04-27 04:35:14 +00:00
Port : int32 ( svcInfo . proxyPort ) ,
2015-03-13 15:16:41 +00:00
Protocol : "UDP" ,
} } } ,
2017-05-04 13:28:15 +00:00
} )
2019-03-29 14:25:21 +00:00
svcInfo , exists := waitForServiceInfo ( p , service )
2015-02-04 06:45:00 +00:00
if ! exists {
t . Fatalf ( "can't find serviceInfo" )
}
2014-09-18 23:03:34 +00:00
testEchoUDP ( t , "127.0.0.1" , svcInfo . proxyPort )
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
}
2014-09-10 20:44:20 +00:00
func TestTCPProxyUpdatePort ( t * testing . T ) {
2014-07-30 13:52:03 +00:00
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-10 20:44:20 +00:00
} )
2014-07-30 13:52:03 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-07-30 13:52:03 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "TCP" , 0 , time . Second )
2014-07-30 13:52:03 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2015-02-03 22:37:41 +00:00
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
waitForNumProxyLoops ( t , p , 1 )
2014-07-30 13:52:03 +00:00
2018-08-15 13:51:19 +00:00
p . OnServiceAdd ( & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
Port : 99 ,
Protocol : "TCP" ,
} } } ,
2017-05-04 13:28:15 +00:00
} )
2015-02-04 06:45:00 +00:00
// Wait for the socket to actually get free.
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortTCP ( p , svcInfo . proxyPort ) ; err != nil {
2014-08-04 19:35:03 +00:00
t . Fatalf ( err . Error ( ) )
2014-06-06 23:40:48 +00:00
}
2019-03-29 14:25:21 +00:00
svcInfo , exists := waitForServiceInfo ( p , service )
2015-02-04 06:45:00 +00:00
if ! exists {
t . Fatalf ( "can't find serviceInfo" )
}
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
2015-02-03 22:37:41 +00:00
// This is a bit async, but this should be sufficient.
time . Sleep ( 500 * time . Millisecond )
waitForNumProxyLoops ( t , p , 1 )
2014-08-19 19:24:10 +00:00
}
2014-09-11 16:00:06 +00:00
func TestUDPProxyUpdatePort ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : udpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2014-09-11 16:00:06 +00:00
} )
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2014-09-11 16:00:06 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "UDP" , 0 , time . Second )
2014-09-11 16:00:06 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
2015-02-03 22:37:41 +00:00
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
2018-08-15 13:51:19 +00:00
p . OnServiceAdd ( & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
Port : 99 ,
Protocol : "UDP" ,
} } } ,
2017-05-04 13:28:15 +00:00
} )
2015-02-04 06:45:00 +00:00
// Wait for the socket to actually get free.
2014-09-18 23:03:34 +00:00
if err := waitForClosedPortUDP ( p , svcInfo . proxyPort ) ; err != nil {
2014-09-11 16:00:06 +00:00
t . Fatalf ( err . Error ( ) )
}
2019-03-29 14:25:21 +00:00
svcInfo , exists := waitForServiceInfo ( p , service )
2015-02-04 06:45:00 +00:00
if ! exists {
t . Fatalf ( "can't find serviceInfo" )
2014-09-11 16:00:06 +00:00
}
2015-02-04 06:45:00 +00:00
testEchoUDP ( t , "127.0.0.1" , svcInfo . proxyPort )
waitForNumProxyLoops ( t , p , 1 )
2014-09-11 16:00:06 +00:00
}
2014-09-11 16:50:20 +00:00
2015-03-27 23:26:00 +00:00
func TestProxyUpdatePublicIPs ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
lb . OnEndpointsAdd ( & v1 . Endpoints {
2017-03-20 13:02:35 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2017-03-20 13:02:35 +00:00
} } ,
2015-03-27 23:26:00 +00:00
} )
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2015-03-27 23:26:00 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "TCP" , 0 , time . Second )
2015-03-27 23:26:00 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
waitForNumProxyLoops ( t , p , 1 )
2018-08-15 13:51:19 +00:00
p . OnServiceAdd ( & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec {
Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
2016-04-27 04:35:14 +00:00
Port : int32 ( svcInfo . portal . port ) ,
2015-03-13 15:16:41 +00:00
Protocol : "TCP" ,
} } ,
2015-08-12 00:18:21 +00:00
ClusterIP : svcInfo . portal . ip . String ( ) ,
ExternalIPs : [ ] string { "4.3.2.1" } ,
2015-03-13 15:16:41 +00:00
} ,
2017-05-04 13:28:15 +00:00
} )
2015-03-27 23:26:00 +00:00
// Wait for the socket to actually get free.
if err := waitForClosedPortTCP ( p , svcInfo . proxyPort ) ; err != nil {
t . Fatalf ( err . Error ( ) )
}
2019-03-29 14:25:21 +00:00
svcInfo , exists := waitForServiceInfo ( p , service )
2015-03-27 23:26:00 +00:00
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 )
}
2015-03-16 21:36:30 +00:00
func TestProxyUpdatePortal ( t * testing . T ) {
lb := NewLoadBalancerRR ( )
2015-08-08 01:52:23 +00:00
service := proxy . ServicePortName { NamespacedName : types . NamespacedName { Namespace : "testnamespace" , Name : "echo" } , Port : "p" }
2018-08-15 13:51:19 +00:00
endpoint := & v1 . Endpoints {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Subsets : [ ] v1 . EndpointSubset { {
Addresses : [ ] v1 . EndpointAddress { { IP : "127.0.0.1" } } ,
Ports : [ ] v1 . EndpointPort { { Name : "p" , Port : tcpServerPort } } ,
2016-07-08 00:43:22 +00:00
} } ,
}
2017-03-20 13:02:35 +00:00
lb . OnEndpointsAdd ( endpoint )
2015-03-16 21:36:30 +00:00
2016-07-22 18:26:36 +00:00
fexec := makeFakeExec ( )
p , err := createProxier ( lb , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Second , udpIdleTimeoutForTest , newProxySocket )
2015-05-14 20:03:30 +00:00
if err != nil {
t . Fatal ( err )
}
2019-03-29 14:25:21 +00:00
startProxier ( p , t )
2019-03-31 19:41:11 +00:00
defer p . shutdown ( )
2015-03-16 21:36:30 +00:00
2017-05-02 11:43:42 +00:00
svcInfo , err := p . addServiceOnPort ( service , "TCP" , 0 , time . Second )
2015-03-16 21:36:30 +00:00
if err != nil {
t . Fatalf ( "error adding new service: %#v" , err )
}
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
waitForNumProxyLoops ( t , p , 1 )
2018-08-15 13:51:19 +00:00
svcv0 := & v1 . Service {
2017-05-04 13:28:15 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2017-05-04 13:28:15 +00:00
Name : "p" ,
Port : int32 ( svcInfo . proxyPort ) ,
Protocol : "TCP" ,
} } } ,
}
2018-08-15 13:51:19 +00:00
svcv1 := & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
2016-04-27 04:35:14 +00:00
Port : int32 ( svcInfo . proxyPort ) ,
2015-03-13 15:16:41 +00:00
Protocol : "TCP" ,
} } } ,
2017-05-04 13:28:15 +00:00
}
p . OnServiceUpdate ( svcv0 , svcv1 )
2019-03-29 14:25:21 +00:00
// Wait for the service to be removed because it had an empty ClusterIP
var exists bool
for i := 0 ; i < 50 ; i ++ {
_ , exists = p . getServiceInfo ( service )
if ! exists {
break
}
time . Sleep ( 50 * time . Millisecond )
}
2015-03-16 21:36:30 +00:00
if exists {
2015-05-23 20:41:11 +00:00
t . Fatalf ( "service with empty ClusterIP should not be included in the proxy" )
2015-03-16 21:36:30 +00:00
}
2018-08-15 13:51:19 +00:00
svcv2 := & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "None" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
2016-04-27 04:35:14 +00:00
Port : int32 ( svcInfo . proxyPort ) ,
2015-03-13 15:16:41 +00:00
Protocol : "TCP" ,
} } } ,
2017-05-04 13:28:15 +00:00
}
p . OnServiceUpdate ( svcv1 , svcv2 )
2015-03-16 21:36:30 +00:00
_ , exists = p . getServiceInfo ( service )
if exists {
2015-05-23 20:41:11 +00:00
t . Fatalf ( "service with 'None' as ClusterIP should not be included in the proxy" )
2015-03-16 21:36:30 +00:00
}
2018-08-15 13:51:19 +00:00
svcv3 := & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : service . Name , Namespace : service . Namespace } ,
2018-08-15 13:51:19 +00:00
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
2015-03-13 15:16:41 +00:00
Name : "p" ,
2016-04-27 04:35:14 +00:00
Port : int32 ( svcInfo . proxyPort ) ,
2015-03-13 15:16:41 +00:00
Protocol : "TCP" ,
} } } ,
2017-05-04 13:28:15 +00:00
}
p . OnServiceUpdate ( svcv2 , svcv3 )
2017-03-20 13:02:35 +00:00
lb . OnEndpointsAdd ( endpoint )
2019-03-29 14:25:21 +00:00
svcInfo , exists = waitForServiceInfo ( p , service )
2015-03-16 21:36:30 +00:00
if ! exists {
2015-05-23 20:41:11 +00:00
t . Fatalf ( "service with ClusterIP set not found in the proxy" )
2015-03-16 21:36:30 +00:00
}
testEchoTCP ( t , "127.0.0.1" , svcInfo . proxyPort )
waitForNumProxyLoops ( t , p , 1 )
}
2019-03-29 14:25:21 +00:00
type fakeRunner struct { }
// assert fakeAsyncRunner is a ProxyProvider
var _ asyncRunnerInterface = & fakeRunner { }
func ( f fakeRunner ) Run ( ) {
}
func ( f fakeRunner ) Loop ( stop <- chan struct { } ) {
}
func TestOnServiceAddChangeMap ( t * testing . T ) {
fexec := makeFakeExec ( )
// Use long minSyncPeriod so we can test that immediate syncs work
p , err := createProxier ( NewLoadBalancerRR ( ) , net . ParseIP ( "0.0.0.0" ) , ipttest . NewFake ( ) , fexec , net . ParseIP ( "127.0.0.1" ) , nil , time . Minute , time . Minute , udpIdleTimeoutForTest , newProxySocket )
if err != nil {
t . Fatal ( err )
}
// Fake out sync runner
p . syncRunner = fakeRunner { }
serviceMeta := metav1 . ObjectMeta { Namespace : "testnamespace" , Name : "testname" }
service := & v1 . Service {
ObjectMeta : serviceMeta ,
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.4" , Ports : [ ] v1 . ServicePort { {
Name : "p" ,
Port : 99 ,
Protocol : "TCP" ,
} } } ,
}
serviceUpdate := & v1 . Service {
ObjectMeta : serviceMeta ,
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.5" , Ports : [ ] v1 . ServicePort { {
Name : "p" ,
Port : 100 ,
Protocol : "TCP" ,
} } } ,
}
serviceUpdate2 := & v1 . Service {
ObjectMeta : serviceMeta ,
Spec : v1 . ServiceSpec { ClusterIP : "1.2.3.6" , Ports : [ ] v1 . ServicePort { {
Name : "p" ,
Port : 101 ,
Protocol : "TCP" ,
} } } ,
}
type onServiceTest struct {
detail string
changes [ ] serviceChange
expectedChange * serviceChange
}
tests := [ ] onServiceTest {
{
detail : "add" ,
changes : [ ] serviceChange {
{ current : service } ,
} ,
expectedChange : & serviceChange {
current : service ,
} ,
} ,
{
detail : "add+update=add" ,
changes : [ ] serviceChange {
{ current : service } ,
{
previous : service ,
current : serviceUpdate ,
} ,
} ,
expectedChange : & serviceChange {
current : serviceUpdate ,
} ,
} ,
{
detail : "add+del=none" ,
changes : [ ] serviceChange {
{ current : service } ,
{ previous : service } ,
} ,
} ,
{
detail : "update+update=update" ,
changes : [ ] serviceChange {
{
previous : service ,
current : serviceUpdate ,
} ,
{
previous : serviceUpdate ,
current : serviceUpdate2 ,
} ,
} ,
expectedChange : & serviceChange {
previous : service ,
current : serviceUpdate2 ,
} ,
} ,
{
detail : "update+del=del" ,
changes : [ ] serviceChange {
{
previous : service ,
current : serviceUpdate ,
} ,
{ previous : serviceUpdate } ,
} ,
// change collapsing always keeps the oldest service
// info since correct unmerging depends on the least
// recent update, not the most current.
expectedChange : & serviceChange {
previous : service ,
} ,
} ,
{
detail : "del+add=update" ,
changes : [ ] serviceChange {
{ previous : service } ,
{ current : serviceUpdate } ,
} ,
expectedChange : & serviceChange {
previous : service ,
current : serviceUpdate ,
} ,
} ,
}
for _ , test := range tests {
for _ , change := range test . changes {
p . serviceChange ( change . previous , change . current , test . detail )
}
if test . expectedChange != nil {
if len ( p . serviceChanges ) != 1 {
t . Fatalf ( "[%s] expected 1 service change but found %d" , test . detail , len ( p . serviceChanges ) )
}
expectedService := test . expectedChange . current
if expectedService == nil {
expectedService = test . expectedChange . previous
}
svcName := types . NamespacedName { Namespace : expectedService . Namespace , Name : expectedService . Name }
change , ok := p . serviceChanges [ svcName ]
if ! ok {
t . Fatalf ( "[%s] did not find service change for %v" , test . detail , svcName )
}
if ! reflect . DeepEqual ( change . previous , test . expectedChange . previous ) {
t . Fatalf ( "[%s] change previous service and expected previous service don't match\nchange: %+v\nexp: %+v" , test . detail , change . previous , test . expectedChange . previous )
}
if ! reflect . DeepEqual ( change . current , test . expectedChange . current ) {
t . Fatalf ( "[%s] change current service and expected current service don't match\nchange: %+v\nexp: %+v" , test . detail , change . current , test . expectedChange . current )
}
} else {
if len ( p . serviceChanges ) != 0 {
t . Fatalf ( "[%s] expected no service changes but found %d" , test . detail , len ( p . serviceChanges ) )
}
}
}
}
2017-07-19 05:58:53 +00:00
func makeFakeExec ( ) * fakeexec . FakeExec {
fcmd := fakeexec . FakeCmd {
CombinedOutputScript : [ ] fakeexec . FakeCombinedOutputAction {
2016-07-22 18:26:36 +00:00
func ( ) ( [ ] byte , error ) { return [ ] byte ( "1 flow entries have been deleted" ) , nil } ,
} ,
}
2017-07-19 05:58:53 +00:00
return & fakeexec . FakeExec {
CommandScript : [ ] fakeexec . FakeCommandAction {
func ( cmd string , args ... string ) exec . Cmd { return fakeexec . InitFakeCmd ( & fcmd , cmd , args ... ) } ,
2016-07-22 18:26:36 +00:00
} ,
LookPathFunc : func ( cmd string ) ( string , error ) { return cmd , nil } ,
}
}
2015-05-22 21:19:45 +00:00
// TODO(justinsb): Add test for nodePort conflict detection, once we have nodePort wired in