@@ -20,9 +20,10 @@ limitations under the License.
20
20
package integration
21
21
22
22
import (
23
+ "bufio"
23
24
"context"
24
25
"fmt"
25
- "net/http "
26
+ "net"
26
27
"strings"
27
28
"testing"
28
29
"time"
@@ -38,9 +39,12 @@ import (
38
39
39
40
const (
40
41
tcprouteSampleKustomize = "../../config/tests/tcproute"
42
+ tcprouteRRKustomize = "../../config/tests/tcproute-rr"
41
43
tcprouteSampleName = "blixt-tcproute-sample"
42
44
)
43
45
46
+ var tcpServerNames = []string {"blixt-tcproute-sample" , "tcproute-rr-v1" , "tcproute-rr-v2" }
47
+
44
48
func TestTCPRouteBasics (t * testing.T ) {
45
49
tcpRouteBasicsCleanupKey := "tcproutebasics"
46
50
defer func () {
@@ -69,38 +73,156 @@ func TestTCPRouteBasics(t *testing.T) {
69
73
require .Equal (t , gatewayv1beta1 .IPAddressType , * gw .Status .Addresses [0 ].Type )
70
74
gwaddr := fmt .Sprintf ("%s:8080" , gw .Status .Addresses [0 ].Value )
71
75
72
- t .Log ("waiting for HTTP server to be available" )
76
+ t .Log ("waiting for TCP server to be available" )
73
77
require .Eventually (t , func () bool {
74
78
server , err := env .Cluster ().Client ().AppsV1 ().Deployments (corev1 .NamespaceDefault ).Get (ctx , tcprouteSampleName , metav1.GetOptions {})
75
79
require .NoError (t , err )
76
80
return server .Status .AvailableReplicas > 0
77
81
}, time .Minute , time .Second )
78
82
79
- t .Log ("verifying HTTP connectivity to the server" )
80
- httpc := http. Client { Timeout : time . Second * 30 }
83
+ t .Log ("verifying TCP connectivity to the server" )
84
+ var conn net. Conn
81
85
require .Eventually (t , func () bool {
82
- resp , err := httpc .Get (fmt .Sprintf ("http://%s/status/%d" , gwaddr , http .StatusTeapot ))
86
+ var err error
87
+ conn , err = net .Dial ("tcp" , gwaddr )
83
88
if err != nil {
84
- t .Logf ("received error checking HTTP server: [%s], retrying..." , err )
89
+ t .Logf ("received error connecting to TCP server: [%s], retrying..." , err )
85
90
return false
86
91
}
87
- defer resp .Body .Close ()
88
- return resp .StatusCode == http .StatusTeapot
92
+ return true
89
93
}, time .Minute * 5 , time .Second )
90
94
91
- t .Log ("deleting the TCPRoute and verifying that HTTP traffic stops" )
95
+ writeAndReadTCP (t , conn , tcpServerNames [0 ])
96
+
97
+ t .Log ("deleting the TCPRoute and verifying that TCP connection is closed" )
92
98
require .NoError (t , gwclient .GatewayV1alpha2 ().TCPRoutes (corev1 .NamespaceDefault ).Delete (ctx , tcprouteSampleName , metav1.DeleteOptions {}))
93
- httpc = http.Client {Timeout : time .Second * 3 }
94
99
require .Eventually (t , func () bool {
95
- resp , err := httpc .Get (fmt .Sprintf ("http://%s/status/%d" , gwaddr , http .StatusTeapot ))
100
+ _ , err := conn .Write ([]byte ("blahhh\n " ))
101
+ require .NoError (t , err )
102
+
103
+ err = conn .SetReadDeadline (time .Now ().Add (time .Second * 3 ))
104
+ require .NoError (t , err )
105
+ reader := bufio .NewReader (conn )
106
+ _ , err = reader .ReadBytes (byte ('\n' ))
96
107
if err != nil {
97
- if strings .Contains (err .Error (), "context deadline exceeded " ) {
108
+ if strings .Contains (err .Error (), "i/o timeout " ) {
98
109
return true
99
110
}
100
111
t .Logf ("received unexpected error waiting for TCPRoute to decomission: %s" , err )
101
112
return false
102
113
}
103
- defer resp .Body .Close ()
104
114
return false
105
115
}, time .Minute , time .Second )
106
116
}
117
+
118
+ func TestTCPRouteRoundRobin (t * testing.T ) {
119
+ tcpRouteRRCleanupKey := "tcprouterr"
120
+ defer func () {
121
+ testutils .DumpDiagnosticsIfFailed (ctx , t , env .Cluster ())
122
+ if err := runCleanup (tcpRouteRRCleanupKey ); err != nil {
123
+ t .Errorf ("cleanup failed: %s" , err )
124
+ }
125
+ }()
126
+
127
+ t .Log ("deploying config/samples/tcproute-rr kustomize" )
128
+ require .NoError (t , clusters .KustomizeDeployForCluster (ctx , env .Cluster (), tcprouteRRKustomize ))
129
+ addCleanup (tcpRouteRRCleanupKey , func (ctx context.Context ) error {
130
+ cleanupLog ("cleaning up config/samples/tcproute-rr kustomize" )
131
+ return clusters .KustomizeDeleteForCluster (ctx , env .Cluster (), tcprouteRRKustomize , "--ignore-not-found=true" )
132
+ })
133
+
134
+ t .Log ("waiting for Gateway to have an address" )
135
+ var gw * gatewayv1beta1.Gateway
136
+ require .Eventually (t , func () bool {
137
+ var err error
138
+ gw , err = gwclient .GatewayV1beta1 ().Gateways (corev1 .NamespaceDefault ).Get (ctx , tcprouteSampleName , metav1.GetOptions {})
139
+ require .NoError (t , err )
140
+ return len (gw .Status .Addresses ) > 0
141
+ }, time .Minute , time .Second )
142
+ require .NotNil (t , gw .Status .Addresses [0 ].Type )
143
+ require .Equal (t , gatewayv1beta1 .IPAddressType , * gw .Status .Addresses [0 ].Type )
144
+ gwaddr := fmt .Sprintf ("%s:8080" , gw .Status .Addresses [0 ].Value )
145
+
146
+ t .Log ("waiting for TCP servers to be available" )
147
+ labelSelector := metav1.LabelSelector {
148
+ MatchExpressions : []metav1.LabelSelectorRequirement {
149
+ {
150
+ Key : "app" ,
151
+ Operator : metav1 .LabelSelectorOpIn ,
152
+ Values : tcpServerNames ,
153
+ },
154
+ },
155
+ }
156
+ require .Eventually (t , func () bool {
157
+ servers , err := env .Cluster ().Client ().AppsV1 ().Deployments (corev1 .NamespaceDefault ).List (ctx , metav1.ListOptions {
158
+ LabelSelector : metav1 .FormatLabelSelector (& labelSelector ),
159
+ })
160
+ require .NoError (t , err )
161
+ for _ , server := range servers .Items {
162
+ if server .Status .AvailableReplicas <= 0 {
163
+ return false
164
+ }
165
+ }
166
+ return true
167
+ }, time .Minute , time .Second )
168
+
169
+ t .Log ("verifying TCP connectivity to the servers" )
170
+ var conn1 net.Conn
171
+ require .Eventually (t , func () bool {
172
+ var err error
173
+ conn1 , err = net .Dial ("tcp" , gwaddr )
174
+ if err != nil {
175
+ t .Logf ("received error connecting to TCP server: [%s], retrying..." , err )
176
+ return false
177
+ }
178
+ return true
179
+ }, time .Minute * 5 , time .Second )
180
+ conn2 , err := net .Dial ("tcp" , gwaddr )
181
+ require .NoError (t , err )
182
+ conn3 , err := net .Dial ("tcp" , gwaddr )
183
+ require .NoError (t , err )
184
+ conns := []net.Conn {conn1 , conn2 , conn3 }
185
+
186
+ for c := 0 ; c < 2 ; c ++ {
187
+ for i , conn := range conns {
188
+ writeAndReadTCP (t , conn , tcpServerNames [i ])
189
+ }
190
+ }
191
+
192
+ t .Log ("deleting the TCPRoute and verifying that all TCP connections are closed" )
193
+ require .NoError (t , gwclient .GatewayV1alpha2 ().TCPRoutes (corev1 .NamespaceDefault ).Delete (ctx , tcprouteSampleName , metav1.DeleteOptions {}))
194
+ require .Eventually (t , func () bool {
195
+ for _ , conn := range conns {
196
+ _ , err := conn .Write ([]byte ("blahhh\n " ))
197
+ require .NoError (t , err )
198
+ err = conn .SetReadDeadline (time .Now ().Add (time .Second * 3 ))
199
+ require .NoError (t , err )
200
+
201
+ reader := bufio .NewReader (conn )
202
+ _ , err = reader .ReadBytes (byte ('\n' ))
203
+ if err != nil {
204
+ if strings .Contains (err .Error (), "i/o timeout" ) {
205
+ continue
206
+ }
207
+ t .Logf ("received unexpected error waiting for TCPRoute to decomission: %s" , err )
208
+ }
209
+ return false
210
+ }
211
+ return true
212
+ }, time .Minute , time .Second )
213
+ }
214
+
215
+ func writeAndReadTCP (t * testing.T , conn net.Conn , prefix string ) {
216
+ t .Helper ()
217
+
218
+ t .Logf ("writing data to TCP connection with server %s" , prefix )
219
+ request := "wazzzaaaa"
220
+ _ , err := conn .Write ([]byte (request + "\n " ))
221
+ require .NoError (t , err )
222
+
223
+ t .Logf ("reading data from TCP connection with server %s" , prefix )
224
+ reader := bufio .NewReader (conn )
225
+ response , err := reader .ReadBytes (byte ('\n' ))
226
+ require .NoError (t , err )
227
+ require .Contains (t , string (response ), fmt .Sprintf ("%s: %s" , prefix , string (request )))
228
+ }
0 commit comments