Merge pull request #16451 from ncdc/exec-interop-testing

Automatic merge from submit-queue

Refactor streaming code to support interop testing

Refactor exec/attach/port forward client and server code to better
support interop testing of different client and server subprotocol
versions.

Fixes #16119
This commit is contained in:
k8s-merge-robot
2016-04-01 17:11:26 -07:00
14 changed files with 894 additions and 804 deletions

View File

@@ -114,20 +114,24 @@ func negotiateProtocol(clientProtocols, serverProtocols []string) string {
return ""
}
// Handshake performs a subprotocol negotiation. If the client did not request
// a specific subprotocol, defaultProtocol is used. If the client did request a
// Handshake performs a subprotocol negotiation. If the client did request a
// subprotocol, Handshake will select the first common value found in
// serverProtocols. If a match is found, Handshake adds a response header
// indicating the chosen subprotocol. If no match is found, HTTP forbidden is
// returned, along with a response header containing the list of protocols the
// server can accept.
func Handshake(req *http.Request, w http.ResponseWriter, serverProtocols []string, defaultProtocol string) (string, error) {
func Handshake(req *http.Request, w http.ResponseWriter, serverProtocols []string) (string, error) {
clientProtocols := req.Header[http.CanonicalHeaderKey(HeaderProtocolVersion)]
if len(clientProtocols) == 0 {
// Kube 1.0 client that didn't support subprotocol negotiation
// TODO remove this defaulting logic once Kube 1.0 is no longer supported
w.Header().Add(HeaderProtocolVersion, defaultProtocol)
return defaultProtocol, nil
// Kube 1.0 clients didn't support subprotocol negotiation.
// TODO require clientProtocols once Kube 1.0 is no longer supported
return "", nil
}
if len(serverProtocols) == 0 {
// Kube 1.0 servers didn't support subprotocol negotiation. This is mainly for testing.
// TODO require serverProtocols once Kube 1.0 is no longer supported
return "", nil
}
negotiatedProtocol := negotiateProtocol(clientProtocols, serverProtocols)

View File

@@ -20,6 +20,8 @@ import (
"net/http"
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
)
type responseWriter struct {
@@ -46,8 +48,6 @@ func (r *responseWriter) Write([]byte) (int, error) {
}
func TestHandshake(t *testing.T) {
defaultProtocol := "default"
tests := map[string]struct {
clientProtocols []string
serverProtocols []string
@@ -57,7 +57,7 @@ func TestHandshake(t *testing.T) {
"no client protocols": {
clientProtocols: []string{},
serverProtocols: []string{"a", "b"},
expectedProtocol: defaultProtocol,
expectedProtocol: "",
},
"no common protocol": {
clientProtocols: []string{"c"},
@@ -83,7 +83,7 @@ func TestHandshake(t *testing.T) {
}
w := newResponseWriter()
negotiated, err := Handshake(req, w, test.serverProtocols, defaultProtocol)
negotiated, err := Handshake(req, w, test.serverProtocols)
// verify negotiated protocol
if e, a := test.expectedProtocol, negotiated; e != a {
@@ -112,8 +112,15 @@ func TestHandshake(t *testing.T) {
t.Errorf("%s: unexpected non-nil w.statusCode: %d", name, w.statusCode)
}
if len(test.expectedProtocol) == 0 {
if len(w.Header()[HeaderProtocolVersion]) > 0 {
t.Errorf("%s: unexpected protocol version response header: %s", w.Header()[HeaderProtocolVersion])
}
continue
}
// verify response headers
if e, a := []string{test.expectedProtocol}, w.Header()[HeaderProtocolVersion]; !reflect.DeepEqual(e, a) {
if e, a := []string{test.expectedProtocol}, w.Header()[HeaderProtocolVersion]; !api.Semantic.DeepEqual(e, a) {
t.Errorf("%s: protocol response header: expected %v, got %v", name, e, a)
}
}