Skip to content

Commit c594704

Browse files
seans3k8s-publishing-bot
authored andcommitted
moving for easier cherry-pick
Kubernetes-commit: ae8e580d3a32385797934b4b4d9f190b43f73c40
1 parent b6e8438 commit c594704

File tree

2 files changed

+97
-97
lines changed

2 files changed

+97
-97
lines changed

tools/remotecommand/fallback_test.go

+61-61
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,67 @@ func TestFallbackClient_SPDYSecondarySucceeds(t *testing.T) {
169169
}
170170
}
171171

172+
func TestFallbackClient_PrimaryAndSecondaryFail(t *testing.T) {
173+
// Create fake WebSocket server. Copy received STDIN data back onto STDOUT stream.
174+
websocketServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
175+
conns, err := webSocketServerStreams(req, w, streamOptionsFromRequest(req))
176+
if err != nil {
177+
w.WriteHeader(http.StatusForbidden)
178+
return
179+
}
180+
defer conns.conn.Close()
181+
// Loopback the STDIN stream onto the STDOUT stream.
182+
_, err = io.Copy(conns.stdoutStream, conns.stdinStream)
183+
require.NoError(t, err)
184+
}))
185+
defer websocketServer.Close()
186+
187+
// Now create the fallback client (executor), and point it to the "websocketServer".
188+
// Must add STDIN and STDOUT query params for the client request.
189+
websocketServer.URL = websocketServer.URL + "?" + "stdin=true" + "&" + "stdout=true"
190+
websocketLocation, err := url.Parse(websocketServer.URL)
191+
require.NoError(t, err)
192+
websocketExecutor, err := NewWebSocketExecutor(&rest.Config{Host: websocketLocation.Host}, "GET", websocketServer.URL)
193+
require.NoError(t, err)
194+
spdyExecutor, err := NewSPDYExecutor(&rest.Config{Host: websocketLocation.Host}, "POST", websocketLocation)
195+
require.NoError(t, err)
196+
// Always fallback to spdyExecutor, but spdyExecutor fails against websocket server.
197+
exec, err := NewFallbackExecutor(websocketExecutor, spdyExecutor, func(error) bool { return true })
198+
require.NoError(t, err)
199+
// Update the websocket executor to request remote command v4, which is unsupported.
200+
fallbackExec, ok := exec.(*FallbackExecutor)
201+
assert.True(t, ok, "error casting executor as FallbackExecutor")
202+
websocketExec, ok := fallbackExec.primary.(*wsStreamExecutor)
203+
assert.True(t, ok, "error casting executor as websocket executor")
204+
// Set the attempted subprotocol version to V4; websocket server only accepts V5.
205+
websocketExec.protocols = []string{remotecommand.StreamProtocolV4Name}
206+
207+
// Generate random data, and set it up to stream on STDIN. The data will be
208+
// returned on the STDOUT buffer.
209+
randomSize := 1024 * 1024
210+
randomData := make([]byte, randomSize)
211+
if _, err := rand.Read(randomData); err != nil {
212+
t.Errorf("unexpected error reading random data: %v", err)
213+
}
214+
var stdout bytes.Buffer
215+
options := &StreamOptions{
216+
Stdin: bytes.NewReader(randomData),
217+
Stdout: &stdout,
218+
}
219+
errorChan := make(chan error)
220+
go func() {
221+
errorChan <- exec.StreamWithContext(context.Background(), *options)
222+
}()
223+
224+
select {
225+
case <-time.After(wait.ForeverTestTimeout):
226+
t.Fatalf("expect stream to be closed after connection is closed.")
227+
case err := <-errorChan:
228+
// Ensure secondary executor returned an error.
229+
require.Error(t, err)
230+
}
231+
}
232+
172233
// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
173234
//
174235
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
@@ -340,64 +401,3 @@ func TestFallbackClient_WebSocketHTTPSProxyCausesSPDYFallback(t *testing.T) {
340401
t.Errorf("expected %d proxy call, got %d", e, a)
341402
}
342403
}
343-
344-
func TestFallbackClient_PrimaryAndSecondaryFail(t *testing.T) {
345-
// Create fake WebSocket server. Copy received STDIN data back onto STDOUT stream.
346-
websocketServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
347-
conns, err := webSocketServerStreams(req, w, streamOptionsFromRequest(req))
348-
if err != nil {
349-
w.WriteHeader(http.StatusForbidden)
350-
return
351-
}
352-
defer conns.conn.Close()
353-
// Loopback the STDIN stream onto the STDOUT stream.
354-
_, err = io.Copy(conns.stdoutStream, conns.stdinStream)
355-
require.NoError(t, err)
356-
}))
357-
defer websocketServer.Close()
358-
359-
// Now create the fallback client (executor), and point it to the "websocketServer".
360-
// Must add STDIN and STDOUT query params for the client request.
361-
websocketServer.URL = websocketServer.URL + "?" + "stdin=true" + "&" + "stdout=true"
362-
websocketLocation, err := url.Parse(websocketServer.URL)
363-
require.NoError(t, err)
364-
websocketExecutor, err := NewWebSocketExecutor(&rest.Config{Host: websocketLocation.Host}, "GET", websocketServer.URL)
365-
require.NoError(t, err)
366-
spdyExecutor, err := NewSPDYExecutor(&rest.Config{Host: websocketLocation.Host}, "POST", websocketLocation)
367-
require.NoError(t, err)
368-
// Always fallback to spdyExecutor, but spdyExecutor fails against websocket server.
369-
exec, err := NewFallbackExecutor(websocketExecutor, spdyExecutor, func(error) bool { return true })
370-
require.NoError(t, err)
371-
// Update the websocket executor to request remote command v4, which is unsupported.
372-
fallbackExec, ok := exec.(*FallbackExecutor)
373-
assert.True(t, ok, "error casting executor as FallbackExecutor")
374-
websocketExec, ok := fallbackExec.primary.(*wsStreamExecutor)
375-
assert.True(t, ok, "error casting executor as websocket executor")
376-
// Set the attempted subprotocol version to V4; websocket server only accepts V5.
377-
websocketExec.protocols = []string{remotecommand.StreamProtocolV4Name}
378-
379-
// Generate random data, and set it up to stream on STDIN. The data will be
380-
// returned on the STDOUT buffer.
381-
randomSize := 1024 * 1024
382-
randomData := make([]byte, randomSize)
383-
if _, err := rand.Read(randomData); err != nil {
384-
t.Errorf("unexpected error reading random data: %v", err)
385-
}
386-
var stdout bytes.Buffer
387-
options := &StreamOptions{
388-
Stdin: bytes.NewReader(randomData),
389-
Stdout: &stdout,
390-
}
391-
errorChan := make(chan error)
392-
go func() {
393-
errorChan <- exec.StreamWithContext(context.Background(), *options)
394-
}()
395-
396-
select {
397-
case <-time.After(wait.ForeverTestTimeout):
398-
t.Fatalf("expect stream to be closed after connection is closed.")
399-
case err := <-errorChan:
400-
// Ensure secondary executor returned an error.
401-
require.Error(t, err)
402-
}
403-
}

tools/remotecommand/websocket_test.go

+36-36
Original file line numberDiff line numberDiff line change
@@ -815,42 +815,6 @@ func TestWebSocketClient_BadHandshake(t *testing.T) {
815815
}
816816
}
817817

818-
// See (https://github.com/kubernetes/kubernetes/issues/126134).
819-
func TestWebSocketClient_HTTPSProxyErrorExpected(t *testing.T) {
820-
urlStr := "http://127.0.0.1/never-used" + "?" + "stdin=true" + "&" + "stdout=true"
821-
websocketLocation, err := url.Parse(urlStr)
822-
if err != nil {
823-
t.Fatalf("Unable to parse WebSocket server URL: %s", urlStr)
824-
}
825-
// proxy url with https scheme will trigger websocket dialing error.
826-
httpsProxyFunc := func(req *http.Request) (*url.URL, error) { return url.Parse("https://127.0.0.1") }
827-
exec, err := NewWebSocketExecutor(&rest.Config{Host: websocketLocation.Host, Proxy: httpsProxyFunc}, "GET", urlStr)
828-
if err != nil {
829-
t.Errorf("unexpected error creating websocket executor: %v", err)
830-
}
831-
var stdout bytes.Buffer
832-
options := &StreamOptions{
833-
Stdout: &stdout,
834-
}
835-
errorChan := make(chan error)
836-
go func() {
837-
// Start the streaming on the WebSocket "exec" client.
838-
errorChan <- exec.StreamWithContext(context.Background(), *options)
839-
}()
840-
841-
select {
842-
case <-time.After(wait.ForeverTestTimeout):
843-
t.Fatalf("expect stream to be closed after connection is closed.")
844-
case err := <-errorChan:
845-
if err == nil {
846-
t.Errorf("expected error but received none")
847-
}
848-
if !httpstream.IsHTTPSProxyError(err) {
849-
t.Errorf("expected https proxy error, got (%s)", err)
850-
}
851-
}
852-
}
853-
854818
// TestWebSocketClient_HeartbeatTimeout tests the heartbeat by forcing a
855819
// timeout by setting the ping period greater than the deadline.
856820
func TestWebSocketClient_HeartbeatTimeout(t *testing.T) {
@@ -1377,3 +1341,39 @@ func createWebSocketStreams(req *http.Request, w http.ResponseWriter, opts *opti
13771341

13781342
return wsStreams, nil
13791343
}
1344+
1345+
// See (https://github.com/kubernetes/kubernetes/issues/126134).
1346+
func TestWebSocketClient_HTTPSProxyErrorExpected(t *testing.T) {
1347+
urlStr := "http://127.0.0.1/never-used" + "?" + "stdin=true" + "&" + "stdout=true"
1348+
websocketLocation, err := url.Parse(urlStr)
1349+
if err != nil {
1350+
t.Fatalf("Unable to parse WebSocket server URL: %s", urlStr)
1351+
}
1352+
// proxy url with https scheme will trigger websocket dialing error.
1353+
httpsProxyFunc := func(req *http.Request) (*url.URL, error) { return url.Parse("https://127.0.0.1") }
1354+
exec, err := NewWebSocketExecutor(&rest.Config{Host: websocketLocation.Host, Proxy: httpsProxyFunc}, "GET", urlStr)
1355+
if err != nil {
1356+
t.Errorf("unexpected error creating websocket executor: %v", err)
1357+
}
1358+
var stdout bytes.Buffer
1359+
options := &StreamOptions{
1360+
Stdout: &stdout,
1361+
}
1362+
errorChan := make(chan error)
1363+
go func() {
1364+
// Start the streaming on the WebSocket "exec" client.
1365+
errorChan <- exec.StreamWithContext(context.Background(), *options)
1366+
}()
1367+
1368+
select {
1369+
case <-time.After(wait.ForeverTestTimeout):
1370+
t.Fatalf("expect stream to be closed after connection is closed.")
1371+
case err := <-errorChan:
1372+
if err == nil {
1373+
t.Errorf("expected error but received none")
1374+
}
1375+
if !httpstream.IsHTTPSProxyError(err) {
1376+
t.Errorf("expected https proxy error, got (%s)", err)
1377+
}
1378+
}
1379+
}

0 commit comments

Comments
 (0)