@@ -27,6 +27,7 @@ import (
27
27
28
28
v1 "k8s.io/api/core/v1"
29
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
+ "k8s.io/apimachinery/pkg/util/httpstream"
30
31
"k8s.io/client-go/kubernetes/scheme"
31
32
restclient "k8s.io/client-go/rest"
32
33
"k8s.io/client-go/tools/remotecommand"
@@ -80,8 +81,8 @@ func ExecWithOptionsContext(ctx context.Context, f *framework.Framework, options
80
81
}, scheme .ParameterCodec )
81
82
82
83
var stdout , stderr bytes.Buffer
83
- framework .Logf ("ExecWithOptions: execute(POST %s)" , req .URL ())
84
- err := execute (ctx , "POST" , req .URL (), f .ClientConfig (), options .Stdin , & stdout , & stderr , tty )
84
+ framework .Logf ("ExecWithOptions: execute(%s)" , req .URL ())
85
+ err := execute (ctx , req .URL (), f .ClientConfig (), options .Stdin , & stdout , & stderr , tty )
85
86
86
87
if options .PreserveWhitespace {
87
88
return stdout .String (), stderr .String (), err
@@ -181,11 +182,29 @@ func VerifyExecInPodFail(ctx context.Context, f *framework.Framework, pod *v1.Po
181
182
return fmt .Errorf ("%q should fail with exit code %d, but exit without error" , shExec , exitCode )
182
183
}
183
184
184
- func execute (ctx context.Context , method string , url * url.URL , config * restclient.Config , stdin io.Reader , stdout , stderr io.Writer , tty bool ) error {
185
- exec , err := remotecommand .NewSPDYExecutor (config , method , url )
185
+ func execute (ctx context.Context , url * url.URL , config * restclient.Config , stdin io.Reader , stdout , stderr io.Writer , tty bool ) error {
186
+ // WebSocketExecutor executor is default
187
+ // WebSocketExecutor must be "GET" method as described in RFC 6455 Sec. 4.1 (page 17).
188
+ websocketExec , err := remotecommand .NewWebSocketExecutor (config , "GET" , url .String ())
186
189
if err != nil {
187
190
return err
188
191
}
192
+ spdyExec , err := remotecommand .NewSPDYExecutor (config , "POST" , url )
193
+ if err != nil {
194
+ return err
195
+ }
196
+ exec , err := remotecommand .NewFallbackExecutor (websocketExec , spdyExec , func (err error ) bool {
197
+ if httpstream .IsUpgradeFailure (err ) || httpstream .IsHTTPSProxyError (err ) {
198
+ framework .Logf ("fallback to secondary dialer from primary dialer err: %v" , err )
199
+ return true
200
+ }
201
+ framework .Logf ("unexpected error trying to use websockets for pod exec: %v" , err )
202
+ return false
203
+ })
204
+ if err != nil {
205
+ return err
206
+ }
207
+
189
208
return exec .StreamWithContext (ctx , remotecommand.StreamOptions {
190
209
Stdin : stdin ,
191
210
Stdout : stdout ,
0 commit comments