diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2017-11-22 07:56:46 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-11-22 20:53:15 +0000 |
commit | c344fe61c11beaf687da284f71bde2311b91371d (patch) | |
tree | d837a4c8ad0df01f15c7e90b052a72e1c39530ca /vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand | |
parent | ee4051db61ad8ce6f385ce5be45dcc4b0a29945d (diff) | |
download | podman-c344fe61c11beaf687da284f71bde2311b91371d.tar.gz podman-c344fe61c11beaf687da284f71bde2311b91371d.tar.bz2 podman-c344fe61c11beaf687da284f71bde2311b91371d.zip |
Update vendoring
Update version of docker to pull in lates code
Remove kubernetes since libpod is not tied to it.
Remove a few other packages that we don't seem to use.
Left in the networking stuff, since we will hopefully be wiring that together.
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Closes: #60
Approved by: umohnani8
Diffstat (limited to 'vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand')
5 files changed, 0 insertions, 735 deletions
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/attach.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/attach.go deleted file mode 100644 index e266f34fe..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/attach.go +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -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. -*/ - -package remotecommand - -import ( - "fmt" - "io" - "net/http" - "time" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" -) - -// Attacher knows how to attach to a running container in a pod. -type Attacher interface { - // AttachContainer attaches to the running container in the pod, copying data between in/out/err - // and the container's stdin/stdout/stderr. - AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error -} - -// ServeAttach handles requests to attach to a container. After creating/receiving the required -// streams, it delegates the actual attaching to attacher. -func ServeAttach(w http.ResponseWriter, req *http.Request, attacher Attacher, podName string, uid types.UID, container string, streamOpts *Options, idleTimeout, streamCreationTimeout time.Duration, supportedProtocols []string) { - ctx, ok := createStreams(req, w, streamOpts, supportedProtocols, idleTimeout, streamCreationTimeout) - if !ok { - // error is handled by createStreams - return - } - defer ctx.conn.Close() - - err := attacher.AttachContainer(podName, uid, container, ctx.stdinStream, ctx.stdoutStream, ctx.stderrStream, ctx.tty, ctx.resizeChan) - if err != nil { - err = fmt.Errorf("error attaching to container: %v", err) - runtime.HandleError(err) - ctx.writeStatus(apierrors.NewInternalError(err)) - } else { - ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusSuccess, - }}) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/doc.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/doc.go deleted file mode 100644 index 24f9393ab..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -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. -*/ - -// package remotecommand contains functions related to executing commands in and attaching to pods. -package remotecommand // import "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/exec.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/exec.go deleted file mode 100644 index 8d14a937a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/exec.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -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. -*/ - -package remotecommand - -import ( - "fmt" - "io" - "net/http" - "time" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" - utilexec "k8s.io/kubernetes/pkg/util/exec" -) - -// Executor knows how to execute a command in a container in a pod. -type Executor interface { - // ExecInContainer executes a command in a container in the pod, copying data - // between in/out/err and the container's stdin/stdout/stderr. - ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error -} - -// ServeExec handles requests to execute a command in a container. After -// creating/receiving the required streams, it delegates the actual execution -// to the executor. -func ServeExec(w http.ResponseWriter, req *http.Request, executor Executor, podName string, uid types.UID, container string, cmd []string, streamOpts *Options, idleTimeout, streamCreationTimeout time.Duration, supportedProtocols []string) { - ctx, ok := createStreams(req, w, streamOpts, supportedProtocols, idleTimeout, streamCreationTimeout) - if !ok { - // error is handled by createStreams - return - } - defer ctx.conn.Close() - - err := executor.ExecInContainer(podName, uid, container, cmd, ctx.stdinStream, ctx.stdoutStream, ctx.stderrStream, ctx.tty, ctx.resizeChan, 0) - if err != nil { - if exitErr, ok := err.(utilexec.ExitError); ok && exitErr.Exited() { - rc := exitErr.ExitStatus() - ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Reason: remotecommandconsts.NonZeroExitCodeReason, - Details: &metav1.StatusDetails{ - Causes: []metav1.StatusCause{ - { - Type: remotecommandconsts.ExitCodeCauseType, - Message: fmt.Sprintf("%d", rc), - }, - }, - }, - Message: fmt.Sprintf("command terminated with non-zero exit code: %v", exitErr), - }}) - } else { - err = fmt.Errorf("error executing command in container: %v", err) - runtime.HandleError(err) - ctx.writeStatus(apierrors.NewInternalError(err)) - } - } else { - ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusSuccess, - }}) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/httpstream.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/httpstream.go deleted file mode 100644 index f09b5e400..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/httpstream.go +++ /dev/null @@ -1,447 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -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. -*/ - -package remotecommand - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "time" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/httpstream" - "k8s.io/apimachinery/pkg/util/httpstream/spdy" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/util/wsstream" - "k8s.io/client-go/tools/remotecommand" - "k8s.io/kubernetes/pkg/api" - - "github.com/golang/glog" -) - -// Options contains details about which streams are required for -// remote command execution. -type Options struct { - Stdin bool - Stdout bool - Stderr bool - TTY bool -} - -// NewOptions creates a new Options from the Request. -func NewOptions(req *http.Request) (*Options, error) { - tty := req.FormValue(api.ExecTTYParam) == "1" - stdin := req.FormValue(api.ExecStdinParam) == "1" - stdout := req.FormValue(api.ExecStdoutParam) == "1" - stderr := req.FormValue(api.ExecStderrParam) == "1" - if tty && stderr { - // TODO: make this an error before we reach this method - glog.V(4).Infof("Access to exec with tty and stderr is not supported, bypassing stderr") - stderr = false - } - - if !stdin && !stdout && !stderr { - return nil, fmt.Errorf("you must specify at least 1 of stdin, stdout, stderr") - } - - return &Options{ - Stdin: stdin, - Stdout: stdout, - Stderr: stderr, - TTY: tty, - }, nil -} - -// context contains the connection and streams used when -// forwarding an attach or execute session into a container. -type context struct { - conn io.Closer - stdinStream io.ReadCloser - stdoutStream io.WriteCloser - stderrStream io.WriteCloser - writeStatus func(status *apierrors.StatusError) error - resizeStream io.ReadCloser - resizeChan chan remotecommand.TerminalSize - tty bool -} - -// streamAndReply holds both a Stream and a channel that is closed when the stream's reply frame is -// enqueued. Consumers can wait for replySent to be closed prior to proceeding, to ensure that the -// replyFrame is enqueued before the connection's goaway frame is sent (e.g. if a stream was -// received and right after, the connection gets closed). -type streamAndReply struct { - httpstream.Stream - replySent <-chan struct{} -} - -// waitStreamReply waits until either replySent or stop is closed. If replySent is closed, it sends -// an empty struct to the notify channel. -func waitStreamReply(replySent <-chan struct{}, notify chan<- struct{}, stop <-chan struct{}) { - select { - case <-replySent: - notify <- struct{}{} - case <-stop: - } -} - -func createStreams(req *http.Request, w http.ResponseWriter, opts *Options, supportedStreamProtocols []string, idleTimeout, streamCreationTimeout time.Duration) (*context, bool) { - var ctx *context - var ok bool - if wsstream.IsWebSocketRequest(req) { - ctx, ok = createWebSocketStreams(req, w, opts, idleTimeout) - } else { - ctx, ok = createHttpStreamStreams(req, w, opts, supportedStreamProtocols, idleTimeout, streamCreationTimeout) - } - if !ok { - return nil, false - } - - if ctx.resizeStream != nil { - ctx.resizeChan = make(chan remotecommand.TerminalSize) - go handleResizeEvents(ctx.resizeStream, ctx.resizeChan) - } - - return ctx, true -} - -func createHttpStreamStreams(req *http.Request, w http.ResponseWriter, opts *Options, supportedStreamProtocols []string, idleTimeout, streamCreationTimeout time.Duration) (*context, bool) { - protocol, err := httpstream.Handshake(req, w, supportedStreamProtocols) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - fmt.Fprint(w, err.Error()) - return nil, false - } - - streamCh := make(chan streamAndReply) - - upgrader := spdy.NewResponseUpgrader() - conn := upgrader.UpgradeResponse(w, req, func(stream httpstream.Stream, replySent <-chan struct{}) error { - streamCh <- streamAndReply{Stream: stream, replySent: replySent} - return nil - }) - // from this point on, we can no longer call methods on response - if conn == nil { - // The upgrader is responsible for notifying the client of any errors that - // occurred during upgrading. All we can do is return here at this point - // if we weren't successful in upgrading. - return nil, false - } - - conn.SetIdleTimeout(idleTimeout) - - var handler protocolHandler - switch protocol { - case remotecommandconsts.StreamProtocolV4Name: - handler = &v4ProtocolHandler{} - case remotecommandconsts.StreamProtocolV3Name: - handler = &v3ProtocolHandler{} - case remotecommandconsts.StreamProtocolV2Name: - handler = &v2ProtocolHandler{} - case "": - glog.V(4).Infof("Client did not request protocol negotiaion. Falling back to %q", remotecommandconsts.StreamProtocolV1Name) - fallthrough - case remotecommandconsts.StreamProtocolV1Name: - handler = &v1ProtocolHandler{} - } - - // count the streams client asked for, starting with 1 - expectedStreams := 1 - if opts.Stdin { - expectedStreams++ - } - if opts.Stdout { - expectedStreams++ - } - if opts.Stderr { - expectedStreams++ - } - if opts.TTY && handler.supportsTerminalResizing() { - expectedStreams++ - } - - expired := time.NewTimer(streamCreationTimeout) - defer expired.Stop() - - ctx, err := handler.waitForStreams(streamCh, expectedStreams, expired.C) - if err != nil { - runtime.HandleError(err) - return nil, false - } - - ctx.conn = conn - ctx.tty = opts.TTY - - return ctx, true -} - -type protocolHandler interface { - // waitForStreams waits for the expected streams or a timeout, returning a - // remoteCommandContext if all the streams were received, or an error if not. - waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) - // supportsTerminalResizing returns true if the protocol handler supports terminal resizing - supportsTerminalResizing() bool -} - -// v4ProtocolHandler implements the V4 protocol version for streaming command execution. It only differs -// in from v3 in the error stream format using an json-marshaled metav1.Status which carries -// the process' exit code. -type v4ProtocolHandler struct{} - -func (*v4ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v4WriteStatusFunc(stream) // write json errors - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeResize: - ctx.resizeStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("Unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - return ctx, nil -} - -// supportsTerminalResizing returns true because v4ProtocolHandler supports it -func (*v4ProtocolHandler) supportsTerminalResizing() bool { return true } - -// v3ProtocolHandler implements the V3 protocol version for streaming command execution. -type v3ProtocolHandler struct{} - -func (*v3ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v1WriteStatusFunc(stream) - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeResize: - ctx.resizeStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("Unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - return ctx, nil -} - -// supportsTerminalResizing returns true because v3ProtocolHandler supports it -func (*v3ProtocolHandler) supportsTerminalResizing() bool { return true } - -// v2ProtocolHandler implements the V2 protocol version for streaming command execution. -type v2ProtocolHandler struct{} - -func (*v2ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v1WriteStatusFunc(stream) - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("Unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - return ctx, nil -} - -// supportsTerminalResizing returns false because v2ProtocolHandler doesn't support it. -func (*v2ProtocolHandler) supportsTerminalResizing() bool { return false } - -// v1ProtocolHandler implements the V1 protocol version for streaming command execution. -type v1ProtocolHandler struct{} - -func (*v1ProtocolHandler) waitForStreams(streams <-chan streamAndReply, expectedStreams int, expired <-chan time.Time) (*context, error) { - ctx := &context{} - receivedStreams := 0 - replyChan := make(chan struct{}) - stop := make(chan struct{}) - defer close(stop) -WaitForStreams: - for { - select { - case stream := <-streams: - streamType := stream.Headers().Get(api.StreamType) - switch streamType { - case api.StreamTypeError: - ctx.writeStatus = v1WriteStatusFunc(stream) - - // This defer statement shouldn't be here, but due to previous refactoring, it ended up in - // here. This is what 1.0.x kubelets do, so we're retaining that behavior. This is fixed in - // the v2ProtocolHandler. - defer stream.Reset() - - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdin: - ctx.stdinStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStdout: - ctx.stdoutStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - case api.StreamTypeStderr: - ctx.stderrStream = stream - go waitStreamReply(stream.replySent, replyChan, stop) - default: - runtime.HandleError(fmt.Errorf("Unexpected stream type: %q", streamType)) - } - case <-replyChan: - receivedStreams++ - if receivedStreams == expectedStreams { - break WaitForStreams - } - case <-expired: - // TODO find a way to return the error to the user. Maybe use a separate - // stream to report errors? - return nil, errors.New("timed out waiting for client to create streams") - } - } - - if ctx.stdinStream != nil { - ctx.stdinStream.Close() - } - - return ctx, nil -} - -// supportsTerminalResizing returns false because v1ProtocolHandler doesn't support it. -func (*v1ProtocolHandler) supportsTerminalResizing() bool { return false } - -func handleResizeEvents(stream io.Reader, channel chan<- remotecommand.TerminalSize) { - defer runtime.HandleCrash() - - decoder := json.NewDecoder(stream) - for { - size := remotecommand.TerminalSize{} - if err := decoder.Decode(&size); err != nil { - break - } - channel <- size - } -} - -func v1WriteStatusFunc(stream io.WriteCloser) func(status *apierrors.StatusError) error { - return func(status *apierrors.StatusError) error { - if status.Status().Status == metav1.StatusSuccess { - return nil // send error messages - } - _, err := stream.Write([]byte(status.Error())) - return err - } -} - -// v4WriteStatusFunc returns a WriteStatusFunc that marshals a given api Status -// as json in the error channel. -func v4WriteStatusFunc(stream io.WriteCloser) func(status *apierrors.StatusError) error { - return func(status *apierrors.StatusError) error { - bs, err := json.Marshal(status.Status()) - if err != nil { - return err - } - _, err = stream.Write(bs) - return err - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go deleted file mode 100644 index c60012b21..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/remotecommand/websocket.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -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. -*/ - -package remotecommand - -import ( - "fmt" - "net/http" - "time" - - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/server/httplog" - "k8s.io/apiserver/pkg/util/wsstream" -) - -const ( - stdinChannel = iota - stdoutChannel - stderrChannel - errorChannel - resizeChannel - - preV4BinaryWebsocketProtocol = wsstream.ChannelWebSocketProtocol - preV4Base64WebsocketProtocol = wsstream.Base64ChannelWebSocketProtocol - v4BinaryWebsocketProtocol = "v4." + wsstream.ChannelWebSocketProtocol - v4Base64WebsocketProtocol = "v4." + wsstream.Base64ChannelWebSocketProtocol -) - -// createChannels returns the standard channel types for a shell connection (STDIN 0, STDOUT 1, STDERR 2) -// along with the approximate duplex value. It also creates the error (3) and resize (4) channels. -func createChannels(opts *Options) []wsstream.ChannelType { - // open the requested channels, and always open the error channel - channels := make([]wsstream.ChannelType, 5) - channels[stdinChannel] = readChannel(opts.Stdin) - channels[stdoutChannel] = writeChannel(opts.Stdout) - channels[stderrChannel] = writeChannel(opts.Stderr) - channels[errorChannel] = wsstream.WriteChannel - channels[resizeChannel] = wsstream.ReadChannel - return channels -} - -// readChannel returns wsstream.ReadChannel if real is true, or wsstream.IgnoreChannel. -func readChannel(real bool) wsstream.ChannelType { - if real { - return wsstream.ReadChannel - } - return wsstream.IgnoreChannel -} - -// writeChannel returns wsstream.WriteChannel if real is true, or wsstream.IgnoreChannel. -func writeChannel(real bool) wsstream.ChannelType { - if real { - return wsstream.WriteChannel - } - return wsstream.IgnoreChannel -} - -// createWebSocketStreams returns a context containing the websocket connection and -// streams needed to perform an exec or an attach. -func createWebSocketStreams(req *http.Request, w http.ResponseWriter, opts *Options, idleTimeout time.Duration) (*context, bool) { - channels := createChannels(opts) - conn := wsstream.NewConn(map[string]wsstream.ChannelProtocolConfig{ - "": { - Binary: true, - Channels: channels, - }, - preV4BinaryWebsocketProtocol: { - Binary: true, - Channels: channels, - }, - preV4Base64WebsocketProtocol: { - Binary: false, - Channels: channels, - }, - v4BinaryWebsocketProtocol: { - Binary: true, - Channels: channels, - }, - v4Base64WebsocketProtocol: { - Binary: false, - Channels: channels, - }, - }) - conn.SetIdleTimeout(idleTimeout) - negotiatedProtocol, streams, err := conn.Open(httplog.Unlogged(w), req) - if err != nil { - runtime.HandleError(fmt.Errorf("Unable to upgrade websocket connection: %v", err)) - return nil, false - } - - // Send an empty message to the lowest writable channel to notify the client the connection is established - // TODO: make generic to SPDY and WebSockets and do it outside of this method? - switch { - case opts.Stdout: - streams[stdoutChannel].Write([]byte{}) - case opts.Stderr: - streams[stderrChannel].Write([]byte{}) - default: - streams[errorChannel].Write([]byte{}) - } - - ctx := &context{ - conn: conn, - stdinStream: streams[stdinChannel], - stdoutStream: streams[stdoutChannel], - stderrStream: streams[stderrChannel], - tty: opts.TTY, - resizeStream: streams[resizeChannel], - } - - switch negotiatedProtocol { - case v4BinaryWebsocketProtocol, v4Base64WebsocketProtocol: - ctx.writeStatus = v4WriteStatusFunc(streams[errorChannel]) - default: - ctx.writeStatus = v1WriteStatusFunc(streams[errorChannel]) - } - - return ctx, true -} |