Decouple remotecommand client from term/kubelet dependencies

In order to move client/unversioned/remotecommand to client-go as a followup
for this change we have to decouple it from tons of dependencies
This commit is contained in:
Dmitry Shulyak 2017-02-15 12:34:49 +02:00
parent e9a91b8cca
commit f50480c714
45 changed files with 222 additions and 184 deletions

View File

@ -14,6 +14,7 @@ go_test(
"fake_client_test.go", "fake_client_test.go",
"listwatch_test.go", "listwatch_test.go",
"portfoward_test.go", "portfoward_test.go",
"remotecommand_test.go",
], ],
library = ":go_default_library", library = ":go_default_library",
tags = ["automanaged"], tags = ["automanaged"],
@ -26,10 +27,15 @@ go_test(
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library", "//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library", "//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/portforward:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library",
"//vendor:github.com/stretchr/testify/require",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/fields", "//vendor:k8s.io/apimachinery/pkg/fields",
"//vendor:k8s.io/apimachinery/pkg/runtime", "//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/httpstream",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/apimachinery/pkg/watch", "//vendor:k8s.io/apimachinery/pkg/watch",
"//vendor:k8s.io/client-go/pkg/api/install", "//vendor:k8s.io/client-go/pkg/api/install",
"//vendor:k8s.io/client-go/rest", "//vendor:k8s.io/client-go/rest",

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package remotecommand package tests
import ( import (
"bytes" "bytes"
@ -34,11 +34,12 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/httpstream"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
remoteclient "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand" "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/util/term"
) )
type fakeExecutor struct { type fakeExecutor struct {
@ -55,11 +56,11 @@ type fakeExecutor struct {
exec bool exec bool
} }
func (ex *fakeExecutor) ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (ex *fakeExecutor) ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remoteclient.TerminalSize, timeout time.Duration) error {
return ex.run(name, uid, container, cmd, in, out, err, tty) return ex.run(name, uid, container, cmd, in, out, err, tty)
} }
func (ex *fakeExecutor) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error { func (ex *fakeExecutor) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remoteclient.TerminalSize) error {
return ex.run(name, uid, container, nil, in, out, err, tty) return ex.run(name, uid, container, nil, in, out, err, tty)
} }
@ -151,8 +152,8 @@ func TestStream(t *testing.T) {
TestName: "error", TestName: "error",
Error: "bail", Error: "bail",
Stdout: "a", Stdout: "a",
ClientProtocols: []string{remotecommand.StreamProtocolV2Name}, ClientProtocols: []string{remotecommandconsts.StreamProtocolV2Name},
ServerProtocols: []string{remotecommand.StreamProtocolV2Name}, ServerProtocols: []string{remotecommandconsts.StreamProtocolV2Name},
}, },
{ {
TestName: "in/out/err", TestName: "in/out/err",
@ -160,8 +161,8 @@ func TestStream(t *testing.T) {
Stdout: "b", Stdout: "b",
Stderr: "c", Stderr: "c",
MessageCount: 100, MessageCount: 100,
ClientProtocols: []string{remotecommand.StreamProtocolV2Name}, ClientProtocols: []string{remotecommandconsts.StreamProtocolV2Name},
ServerProtocols: []string{remotecommand.StreamProtocolV2Name}, ServerProtocols: []string{remotecommandconsts.StreamProtocolV2Name},
}, },
{ {
TestName: "in/out/tty", TestName: "in/out/tty",
@ -169,8 +170,8 @@ func TestStream(t *testing.T) {
Stdout: "b", Stdout: "b",
Tty: true, Tty: true,
MessageCount: 100, MessageCount: 100,
ClientProtocols: []string{remotecommand.StreamProtocolV2Name}, ClientProtocols: []string{remotecommandconsts.StreamProtocolV2Name},
ServerProtocols: []string{remotecommand.StreamProtocolV2Name}, ServerProtocols: []string{remotecommandconsts.StreamProtocolV2Name},
}, },
{ {
// 1.0 kubectl, 1.0 kubelet // 1.0 kubectl, 1.0 kubelet
@ -188,7 +189,7 @@ func TestStream(t *testing.T) {
Stderr: "c", Stderr: "c",
MessageCount: 1, MessageCount: 1,
ClientProtocols: []string{}, ClientProtocols: []string{},
ServerProtocols: []string{remotecommand.StreamProtocolV2Name, remotecommand.StreamProtocolV1Name}, ServerProtocols: []string{remotecommandconsts.StreamProtocolV2Name, remotecommandconsts.StreamProtocolV1Name},
}, },
{ {
// 1.1+ kubectl, 1.0 kubelet // 1.1+ kubectl, 1.0 kubelet
@ -196,7 +197,7 @@ func TestStream(t *testing.T) {
Stdout: "b", Stdout: "b",
Stderr: "c", Stderr: "c",
MessageCount: 1, MessageCount: 1,
ClientProtocols: []string{remotecommand.StreamProtocolV2Name, remotecommand.StreamProtocolV1Name}, ClientProtocols: []string{remotecommandconsts.StreamProtocolV2Name, remotecommandconsts.StreamProtocolV1Name},
ServerProtocols: []string{}, ServerProtocols: []string{},
}, },
} }
@ -254,12 +255,12 @@ func TestStream(t *testing.T) {
conf := &restclient.Config{ conf := &restclient.Config{
Host: server.URL, Host: server.URL,
} }
e, err := NewExecutor(conf, "POST", req.URL()) e, err := remoteclient.NewExecutor(conf, "POST", req.URL())
if err != nil { if err != nil {
t.Errorf("%s: unexpected error: %v", name, err) t.Errorf("%s: unexpected error: %v", name, err)
continue continue
} }
err = e.Stream(StreamOptions{ err = e.Stream(remoteclient.StreamOptions{
SupportedProtocols: testCase.ClientProtocols, SupportedProtocols: testCase.ClientProtocols,
Stdin: streamIn, Stdin: streamIn,
Stdout: streamOut, Stdout: streamOut,
@ -351,7 +352,7 @@ func TestDial(t *testing.T) {
called = true called = true
return rt return rt
} }
exec, err := NewStreamExecutor(upgrader, testFn, "POST", &url.URL{Host: "something.com", Scheme: "https"}) exec, err := remoteclient.NewStreamExecutor(upgrader, testFn, "POST", &url.URL{Host: "something.com", Scheme: "https"})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -14,6 +14,7 @@ go_library(
"doc.go", "doc.go",
"errorstream.go", "errorstream.go",
"remotecommand.go", "remotecommand.go",
"resize.go",
"v1.go", "v1.go",
"v2.go", "v2.go",
"v3.go", "v3.go",
@ -22,13 +23,12 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/util/exec:go_default_library", "//pkg/util/exec:go_default_library",
"//pkg/util/term:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/util/httpstream", "//vendor:k8s.io/apimachinery/pkg/util/httpstream",
"//vendor:k8s.io/apimachinery/pkg/util/httpstream/spdy", "//vendor:k8s.io/apimachinery/pkg/util/httpstream/spdy",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/client-go/rest", "//vendor:k8s.io/client-go/rest",
"//vendor:k8s.io/client-go/transport", "//vendor:k8s.io/client-go/transport",
@ -38,7 +38,6 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = [ srcs = [
"remotecommand_test.go",
"v2_test.go", "v2_test.go",
"v4_test.go", "v4_test.go",
], ],
@ -46,15 +45,8 @@ go_test(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/util/term:go_default_library",
"//vendor:github.com/stretchr/testify/require",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/httpstream", "//vendor:k8s.io/apimachinery/pkg/util/httpstream",
"//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/client-go/rest",
], ],
) )

View File

@ -26,10 +26,9 @@ import (
"k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/apimachinery/pkg/util/httpstream/spdy" "k8s.io/apimachinery/pkg/util/httpstream/spdy"
"k8s.io/apimachinery/pkg/util/remotecommand"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/transport" "k8s.io/client-go/transport"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/util/term"
) )
// StreamOptions holds information pertaining to the current streaming session: supported stream // StreamOptions holds information pertaining to the current streaming session: supported stream
@ -41,7 +40,7 @@ type StreamOptions struct {
Stdout io.Writer Stdout io.Writer
Stderr io.Writer Stderr io.Writer
Tty bool Tty bool
TerminalSizeQueue term.TerminalSizeQueue TerminalSizeQueue TerminalSizeQueue
} }
// Executor is an interface for transporting shell-style streams. // Executor is an interface for transporting shell-style streams.

View File

@ -0,0 +1,33 @@
/*
Copyright 2017 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
// TermimanlSize and TerminalSizeQueue was a part of k8s.io/kubernetes/pkg/util/term
// and were moved in order to decouple client from other term dependencies
// TerminalSize represents the width and height of a terminal.
type TerminalSize struct {
Width uint16
Height uint16
}
// TerminalSizeQueue is capable of returning terminal resize events as they occur.
type TerminalSizeQueue interface {
// Next returns the new terminal size after the terminal has been resized. It returns nil when
// monitoring has been stopped.
Next() *TerminalSize
}

View File

@ -66,7 +66,6 @@ func (p *streamProtocolV3) handleResizes() {
if p.resizeStream == nil || p.TerminalSizeQueue == nil { if p.resizeStream == nil || p.TerminalSizeQueue == nil {
return return
} }
go func() { go func() {
defer runtime.HandleCrash() defer runtime.HandleCrash()

View File

@ -24,7 +24,7 @@ import (
"sync" "sync"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand" "k8s.io/apimachinery/pkg/util/remotecommand"
"k8s.io/kubernetes/pkg/util/exec" "k8s.io/kubernetes/pkg/util/exec"
) )

View File

@ -92,7 +92,6 @@ go_library(
"//pkg/kubectl/cmd/util/editor:go_default_library", "//pkg/kubectl/cmd/util/editor:go_default_library",
"//pkg/kubectl/metricsutil:go_default_library", "//pkg/kubectl/metricsutil:go_default_library",
"//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/resource:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/kubelet/types:go_default_library", "//pkg/kubelet/types:go_default_library",
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library", "//pkg/printers/internalversion:go_default_library",
@ -127,6 +126,7 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/util/json", "//vendor:k8s.io/apimachinery/pkg/util/json",
"//vendor:k8s.io/apimachinery/pkg/util/jsonmergepatch", "//vendor:k8s.io/apimachinery/pkg/util/jsonmergepatch",
"//vendor:k8s.io/apimachinery/pkg/util/mergepatch", "//vendor:k8s.io/apimachinery/pkg/util/mergepatch",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/apimachinery/pkg/util/sets", "//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/apimachinery/pkg/util/strategicpatch", "//vendor:k8s.io/apimachinery/pkg/util/strategicpatch",
"//vendor:k8s.io/apimachinery/pkg/util/validation", "//vendor:k8s.io/apimachinery/pkg/util/validation",
@ -201,6 +201,7 @@ go_test(
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
"//pkg/apis/policy:go_default_library", "//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library", "//pkg/apis/rbac:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/testing:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util:go_default_library",

View File

@ -27,6 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
@ -34,9 +35,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/util/i18n" "k8s.io/kubernetes/pkg/util/i18n"
"k8s.io/kubernetes/pkg/util/term"
) )
var ( var (
@ -91,19 +90,19 @@ func NewCmdAttach(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer)
// RemoteAttach defines the interface accepted by the Attach command - provided for test stubbing // RemoteAttach defines the interface accepted by the Attach command - provided for test stubbing
type RemoteAttach interface { type RemoteAttach interface {
Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue term.TerminalSizeQueue) error Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error
} }
// DefaultRemoteAttach is the standard implementation of attaching // DefaultRemoteAttach is the standard implementation of attaching
type DefaultRemoteAttach struct{} type DefaultRemoteAttach struct{}
func (*DefaultRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue term.TerminalSizeQueue) error { func (*DefaultRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error {
exec, err := remotecommand.NewExecutor(config, method, url) exec, err := remotecommand.NewExecutor(config, method, url)
if err != nil { if err != nil {
return err return err
} }
return exec.Stream(remotecommand.StreamOptions{ return exec.Stream(remotecommand.StreamOptions{
SupportedProtocols: remotecommandserver.SupportedStreamingProtocols, SupportedProtocols: remotecommandconsts.SupportedStreamingProtocols,
Stdin: stdin, Stdin: stdin,
Stdout: stdout, Stdout: stdout,
Stderr: stderr, Stderr: stderr,
@ -242,7 +241,7 @@ func (p *AttachOptions) Run() error {
// save p.Err so we can print the command prompt message below // save p.Err so we can print the command prompt message below
stderr := p.Err stderr := p.Err
var sizeQueue term.TerminalSizeQueue var sizeQueue remotecommand.TerminalSizeQueue
if t.Raw { if t.Raw {
if size := t.GetSize(); size != nil { if size := t.GetSize(); size != nil {
// fake resizing +1 and then back to normal so that attach-detach-reattach will result in the // fake resizing +1 and then back to normal so that attach-detach-reattach will result in the

View File

@ -34,9 +34,9 @@ import (
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/term"
) )
type fakeRemoteAttach struct { type fakeRemoteAttach struct {
@ -45,7 +45,7 @@ type fakeRemoteAttach struct {
err error err error
} }
func (f *fakeRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue term.TerminalSizeQueue) error { func (f *fakeRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error {
f.method = method f.method = method
f.url = url f.url = url
return f.err return f.err

View File

@ -25,13 +25,13 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand" "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/util/i18n" "k8s.io/kubernetes/pkg/util/i18n"
"k8s.io/kubernetes/pkg/util/interrupt" "k8s.io/kubernetes/pkg/util/interrupt"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/util/term"
@ -86,19 +86,19 @@ func NewCmdExec(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
// RemoteExecutor defines the interface accepted by the Exec command - provided for test stubbing // RemoteExecutor defines the interface accepted by the Exec command - provided for test stubbing
type RemoteExecutor interface { type RemoteExecutor interface {
Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue term.TerminalSizeQueue) error Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error
} }
// DefaultRemoteExecutor is the standard implementation of remote command execution // DefaultRemoteExecutor is the standard implementation of remote command execution
type DefaultRemoteExecutor struct{} type DefaultRemoteExecutor struct{}
func (*DefaultRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue term.TerminalSizeQueue) error { func (*DefaultRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error {
exec, err := remotecommand.NewExecutor(config, method, url) exec, err := remotecommand.NewExecutor(config, method, url)
if err != nil { if err != nil {
return err return err
} }
return exec.Stream(remotecommand.StreamOptions{ return exec.Stream(remotecommand.StreamOptions{
SupportedProtocols: remotecommandserver.SupportedStreamingProtocols, SupportedProtocols: remotecommandconsts.SupportedStreamingProtocols,
Stdin: stdin, Stdin: stdin,
Stdout: stdout, Stdout: stdout,
Stderr: stderr, Stderr: stderr,
@ -284,7 +284,7 @@ func (p *ExecOptions) Run() error {
// ensure we can recover the terminal while attached // ensure we can recover the terminal while attached
t := p.setupTTY() t := p.setupTTY()
var sizeQueue term.TerminalSizeQueue var sizeQueue remotecommand.TerminalSizeQueue
if t.Raw { if t.Raw {
// this call spawns a goroutine to monitor/update the terminal size // this call spawns a goroutine to monitor/update the terminal size
sizeQueue = t.MonitorSize(t.GetSize()) sizeQueue = t.MonitorSize(t.GetSize())

View File

@ -33,6 +33,7 @@ import (
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/util/term"
) )
@ -43,7 +44,7 @@ type fakeRemoteExecutor struct {
execErr error execErr error
} }
func (f *fakeRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue term.TerminalSizeQueue) error { func (f *fakeRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error {
f.method = method f.method = method
f.url = url f.url = url
return f.execErr return f.execErr

View File

@ -44,6 +44,7 @@ go_library(
"//pkg/capabilities:go_default_library", "//pkg/capabilities:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library", "//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/listers/core/v1:go_default_library", "//pkg/client/listers/core/v1:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/fieldpath:go_default_library", "//pkg/fieldpath:go_default_library",
@ -100,7 +101,6 @@ go_library(
"//pkg/util/oom:go_default_library", "//pkg/util/oom:go_default_library",
"//pkg/util/procfs:go_default_library", "//pkg/util/procfs:go_default_library",
"//pkg/util/removeall:go_default_library", "//pkg/util/removeall:go_default_library",
"//pkg/util/term:go_default_library",
"//pkg/version:go_default_library", "//pkg/version:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",

View File

@ -28,12 +28,12 @@ go_library(
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library", "//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/events:go_default_library", "//pkg/kubelet/events:go_default_library",
"//pkg/kubelet/util/format:go_default_library", "//pkg/kubelet/util/format:go_default_library",
"//pkg/kubelet/util/ioutils:go_default_library", "//pkg/kubelet/util/ioutils:go_default_library",
"//pkg/util/hash:go_default_library", "//pkg/util/hash:go_default_library",
"//pkg/util/term:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//third_party/forked/golang/expansion:go_default_library", "//third_party/forked/golang/expansion:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",

View File

@ -18,13 +18,13 @@ package container
import ( import (
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
) )
// handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each // handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each
// term.Size received from the channel. The resize channel must be closed elsewhere to stop the // remotecommand.TerminalSize received from the channel. The resize channel must be closed elsewhere to stop the
// goroutine. // goroutine.
func HandleResizing(resize <-chan term.Size, resizeFunc func(size term.Size)) { func HandleResizing(resize <-chan remotecommand.TerminalSize, resizeFunc func(size remotecommand.TerminalSize)) {
if resize == nil { if resize == nil {
return return
} }

View File

@ -28,8 +28,8 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"k8s.io/kubernetes/pkg/util/term"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
@ -128,7 +128,7 @@ type DirectStreamingRuntime interface {
// Runs the command in the container of the specified pod using nsenter. // Runs the command in the container of the specified pod using nsenter.
// Attaches the processes stdin, stdout, and stderr. Optionally uses a // Attaches the processes stdin, stdout, and stderr. Optionally uses a
// tty. // tty.
ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error
// Forward the specified port from the specified pod to the stream. // Forward the specified port from the specified pod to the stream.
PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error
// ContainerAttach encapsulates the attaching to containers for testability // ContainerAttach encapsulates the attaching to containers for testability
@ -160,7 +160,7 @@ type ImageService interface {
} }
type ContainerAttacher interface { type ContainerAttacher interface {
AttachContainer(id ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) (err error) AttachContainer(id ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) (err error)
} }
type ContainerCommandRunner interface { type ContainerCommandRunner interface {

View File

@ -20,8 +20,8 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",
"//pkg/util/term:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//vendor:github.com/golang/mock/gomock", "//vendor:github.com/golang/mock/gomock",
"//vendor:github.com/stretchr/testify/mock", "//vendor:github.com/stretchr/testify/mock",

View File

@ -27,8 +27,8 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
. "k8s.io/kubernetes/pkg/kubelet/container" . "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/util/term"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
@ -311,7 +311,7 @@ func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*PodS
return &status, f.Err return &status, f.Err
} }
func (f *FakeDirectStreamingRuntime) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (f *FakeDirectStreamingRuntime) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
f.Lock() f.Lock()
defer f.Unlock() defer f.Unlock()
@ -326,7 +326,7 @@ func (f *FakeDirectStreamingRuntime) ExecInContainer(containerID ContainerID, cm
return f.Err return f.Err
} }
func (f *FakeDirectStreamingRuntime) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (f *FakeDirectStreamingRuntime) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
f.Lock() f.Lock()
defer f.Unlock() defer f.Unlock()

View File

@ -24,8 +24,8 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
. "k8s.io/kubernetes/pkg/kubelet/container" . "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/util/term"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
@ -90,12 +90,12 @@ func (r *Mock) GetPodStatus(uid types.UID, name, namespace string) (*PodStatus,
return args.Get(0).(*PodStatus), args.Error(1) return args.Get(0).(*PodStatus), args.Error(1)
} }
func (r *Mock) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (r *Mock) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
args := r.Called(containerID, cmd, stdin, stdout, stderr, tty) args := r.Called(containerID, cmd, stdin, stdout, stderr, tty)
return args.Error(0) return args.Error(0)
} }
func (r *Mock) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (r *Mock) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
args := r.Called(containerID, stdin, stdout, stderr, tty) args := r.Called(containerID, stdin, stdout, stderr, tty)
return args.Error(0) return args.Error(0)
} }

View File

@ -29,6 +29,7 @@ go_library(
deps = [ deps = [
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/api:go_default_library", "//pkg/kubelet/api:go_default_library",
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library", "//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm:go_default_library",
@ -48,7 +49,6 @@ go_library(
"//pkg/kubelet/util/cache:go_default_library", "//pkg/kubelet/util/cache:go_default_library",
"//pkg/kubelet/util/ioutils:go_default_library", "//pkg/kubelet/util/ioutils:go_default_library",
"//pkg/util/hash:go_default_library", "//pkg/util/hash:go_default_library",
"//pkg/util/term:go_default_library",
"//vendor:github.com/blang/semver", "//vendor:github.com/blang/semver",
"//vendor:github.com/docker/engine-api/types", "//vendor:github.com/docker/engine-api/types",
"//vendor:github.com/docker/engine-api/types/container", "//vendor:github.com/docker/engine-api/types/container",

View File

@ -24,11 +24,11 @@ import (
"time" "time"
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"k8s.io/kubernetes/pkg/kubelet/dockertools" "k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubelet/server/streaming" "k8s.io/kubernetes/pkg/kubelet/server/streaming"
"k8s.io/kubernetes/pkg/kubelet/util/ioutils" "k8s.io/kubernetes/pkg/kubelet/util/ioutils"
"k8s.io/kubernetes/pkg/util/term"
) )
type streamingRuntime struct { type streamingRuntime struct {
@ -38,12 +38,12 @@ type streamingRuntime struct {
var _ streaming.Runtime = &streamingRuntime{} var _ streaming.Runtime = &streamingRuntime{}
func (r *streamingRuntime) Exec(containerID string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error { func (r *streamingRuntime) Exec(containerID string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
return r.exec(containerID, cmd, in, out, err, tty, resize, 0) return r.exec(containerID, cmd, in, out, err, tty, resize, 0)
} }
// Internal version of Exec adds a timeout. // Internal version of Exec adds a timeout.
func (r *streamingRuntime) exec(containerID string, cmd []string, in io.Reader, out, errw io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (r *streamingRuntime) exec(containerID string, cmd []string, in io.Reader, out, errw io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
container, err := checkContainerStatus(r.client, containerID) container, err := checkContainerStatus(r.client, containerID)
if err != nil { if err != nil {
return err return err
@ -51,7 +51,7 @@ func (r *streamingRuntime) exec(containerID string, cmd []string, in io.Reader,
return r.execHandler.ExecInContainer(r.client, container, cmd, in, out, errw, tty, resize, timeout) return r.execHandler.ExecInContainer(r.client, container, cmd, in, out, errw, tty, resize, timeout)
} }
func (r *streamingRuntime) Attach(containerID string, in io.Reader, out, errw io.WriteCloser, tty bool, resize <-chan term.Size) error { func (r *streamingRuntime) Attach(containerID string, in io.Reader, out, errw io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
_, err := checkContainerStatus(r.client, containerID) _, err := checkContainerStatus(r.client, containerID)
if err != nil { if err != nil {
return err return err

View File

@ -28,6 +28,7 @@ go_library(
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/credentialprovider:go_default_library", "//pkg/credentialprovider:go_default_library",
"//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm:go_default_library",
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",

View File

@ -52,6 +52,7 @@ import (
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/cm"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
dockersecurity "k8s.io/kubernetes/pkg/kubelet/dockertools/securitycontext" dockersecurity "k8s.io/kubernetes/pkg/kubelet/dockertools/securitycontext"
@ -73,7 +74,6 @@ import (
"k8s.io/kubernetes/pkg/util/selinux" "k8s.io/kubernetes/pkg/util/selinux"
utilstrings "k8s.io/kubernetes/pkg/util/strings" utilstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/util/tail" "k8s.io/kubernetes/pkg/util/tail"
"k8s.io/kubernetes/pkg/util/term"
utilversion "k8s.io/kubernetes/pkg/util/version" utilversion "k8s.io/kubernetes/pkg/util/version"
) )
@ -1297,7 +1297,7 @@ func (d *dockerExitError) ExitStatus() int {
} }
// ExecInContainer runs the command inside the container identified by containerID. // ExecInContainer runs the command inside the container identified by containerID.
func (dm *DockerManager) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (dm *DockerManager) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
if dm.execHandler == nil { if dm.execHandler == nil {
return errors.New("unable to exec without an exec handler") return errors.New("unable to exec without an exec handler")
} }
@ -1313,16 +1313,16 @@ func (dm *DockerManager) ExecInContainer(containerID kubecontainer.ContainerID,
return dm.execHandler.ExecInContainer(dm.client, container, cmd, stdin, stdout, stderr, tty, resize, timeout) return dm.execHandler.ExecInContainer(dm.client, container, cmd, stdin, stdout, stderr, tty, resize, timeout)
} }
func (dm *DockerManager) AttachContainer(containerID kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (dm *DockerManager) AttachContainer(containerID kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
return AttachContainer(dm.client, containerID.ID, stdin, stdout, stderr, tty, resize) return AttachContainer(dm.client, containerID.ID, stdin, stdout, stderr, tty, resize)
} }
// Temporarily export this function to share with dockershim. // Temporarily export this function to share with dockershim.
// TODO: clean this up. // TODO: clean this up.
func AttachContainer(client DockerInterface, containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func AttachContainer(client DockerInterface, containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
// Have to start this before the call to client.AttachToContainer because client.AttachToContainer is a blocking // Have to start this before the call to client.AttachToContainer because client.AttachToContainer is a blocking
// call :-( Otherwise, resize events don't get processed and the terminal never resizes. // call :-( Otherwise, resize events don't get processed and the terminal never resizes.
kubecontainer.HandleResizing(resize, func(size term.Size) { kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
client.ResizeContainerTTY(containerID, int(size.Height), int(size.Width)) client.ResizeContainerTTY(containerID, int(size.Height), int(size.Width))
}) })

View File

@ -25,6 +25,7 @@ import (
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
utilexec "k8s.io/kubernetes/pkg/util/exec" utilexec "k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/util/term"
@ -32,14 +33,14 @@ import (
// ExecHandler knows how to execute a command in a running Docker container. // ExecHandler knows how to execute a command in a running Docker container.
type ExecHandler interface { type ExecHandler interface {
ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error
} }
// NsenterExecHandler executes commands in Docker containers using nsenter. // NsenterExecHandler executes commands in Docker containers using nsenter.
type NsenterExecHandler struct{} type NsenterExecHandler struct{}
// TODO should we support nsenter in a container, running with elevated privs and --pid=host? // TODO should we support nsenter in a container, running with elevated privs and --pid=host?
func (*NsenterExecHandler) ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (*NsenterExecHandler) ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
nsenter, err := exec.LookPath("nsenter") nsenter, err := exec.LookPath("nsenter")
if err != nil { if err != nil {
return fmt.Errorf("exec unavailable - unable to locate nsenter") return fmt.Errorf("exec unavailable - unable to locate nsenter")
@ -64,7 +65,7 @@ func (*NsenterExecHandler) ExecInContainer(client DockerInterface, container *do
// make sure to close the stdout stream // make sure to close the stdout stream
defer stdout.Close() defer stdout.Close()
kubecontainer.HandleResizing(resize, func(size term.Size) { kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
term.SetSize(p.Fd(), size) term.SetSize(p.Fd(), size)
}) })
@ -110,7 +111,7 @@ func (*NsenterExecHandler) ExecInContainer(client DockerInterface, container *do
// NativeExecHandler executes commands in Docker containers using Docker's exec API. // NativeExecHandler executes commands in Docker containers using Docker's exec API.
type NativeExecHandler struct{} type NativeExecHandler struct{}
func (*NativeExecHandler) ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (*NativeExecHandler) ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
createOpts := dockertypes.ExecConfig{ createOpts := dockertypes.ExecConfig{
Cmd: cmd, Cmd: cmd,
AttachStdin: stdin != nil, AttachStdin: stdin != nil,
@ -125,7 +126,7 @@ func (*NativeExecHandler) ExecInContainer(client DockerInterface, container *doc
// Have to start this before the call to client.StartExec because client.StartExec is a blocking // Have to start this before the call to client.StartExec because client.StartExec is a blocking
// call :-( Otherwise, resize events don't get processed and the terminal never resizes. // call :-( Otherwise, resize events don't get processed and the terminal never resizes.
kubecontainer.HandleResizing(resize, func(size term.Size) { kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
client.ResizeExecTTY(execObj.ID, int(size.Height), int(size.Width)) client.ResizeExecTTY(execObj.ID, int(size.Height), int(size.Width))
}) })

View File

@ -44,6 +44,7 @@ import (
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
utilpod "k8s.io/kubernetes/pkg/api/v1/pod" utilpod "k8s.io/kubernetes/pkg/api/v1/pod"
"k8s.io/kubernetes/pkg/api/v1/validation" "k8s.io/kubernetes/pkg/api/v1/validation"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/fieldpath" "k8s.io/kubernetes/pkg/fieldpath"
"k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/cm"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
@ -51,11 +52,10 @@ import (
"k8s.io/kubernetes/pkg/kubelet/images" "k8s.io/kubernetes/pkg/kubelet/images"
"k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/kubelet/qos"
"k8s.io/kubernetes/pkg/kubelet/server/portforward" "k8s.io/kubernetes/pkg/kubelet/server/portforward"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/status"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types" kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/kubelet/util/format"
"k8s.io/kubernetes/pkg/util/term"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util/volumehelper" "k8s.io/kubernetes/pkg/volume/util/volumehelper"
"k8s.io/kubernetes/third_party/forked/golang/expansion" "k8s.io/kubernetes/third_party/forked/golang/expansion"
@ -1412,7 +1412,7 @@ func (kl *Kubelet) RunInContainer(podFullName string, podUID types.UID, containe
// ExecInContainer executes a command in a container, connecting the supplied // ExecInContainer executes a command in a container, connecting the supplied
// stdin/stdout/stderr to the command's IO streams. // stdin/stdout/stderr to the command's IO streams.
func (kl *Kubelet) ExecInContainer(podFullName string, podUID types.UID, containerName string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (kl *Kubelet) ExecInContainer(podFullName string, podUID types.UID, containerName string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime)
if !ok { if !ok {
return fmt.Errorf("streaming methods not supported by runtime") return fmt.Errorf("streaming methods not supported by runtime")
@ -1430,7 +1430,7 @@ func (kl *Kubelet) ExecInContainer(podFullName string, podUID types.UID, contain
// AttachContainer uses the container runtime to attach the given streams to // AttachContainer uses the container runtime to attach the given streams to
// the given container. // the given container.
func (kl *Kubelet) AttachContainer(podFullName string, podUID types.UID, containerName string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (kl *Kubelet) AttachContainer(podFullName string, podUID types.UID, containerName string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime)
if !ok { if !ok {
return fmt.Errorf("streaming methods not supported by runtime") return fmt.Errorf("streaming methods not supported by runtime")
@ -1467,7 +1467,7 @@ func (kl *Kubelet) PortForward(podFullName string, podUID types.UID, port int32,
} }
// GetExec gets the URL the exec will be served from, or nil if the Kubelet will serve it. // GetExec gets the URL the exec will be served from, or nil if the Kubelet will serve it.
func (kl *Kubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommand.Options) (*url.URL, error) { func (kl *Kubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) {
switch streamingRuntime := kl.containerRuntime.(type) { switch streamingRuntime := kl.containerRuntime.(type) {
case kubecontainer.DirectStreamingRuntime: case kubecontainer.DirectStreamingRuntime:
// Kubelet will serve the exec directly. // Kubelet will serve the exec directly.
@ -1487,7 +1487,7 @@ func (kl *Kubelet) GetExec(podFullName string, podUID types.UID, containerName s
} }
// GetAttach gets the URL the attach will be served from, or nil if the Kubelet will serve it. // GetAttach gets the URL the attach will be served from, or nil if the Kubelet will serve it.
func (kl *Kubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommand.Options) (*url.URL, error) { func (kl *Kubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) {
switch streamingRuntime := kl.containerRuntime.(type) { switch streamingRuntime := kl.containerRuntime.(type) {
case kubecontainer.DirectStreamingRuntime: case kubecontainer.DirectStreamingRuntime:
// Kubelet will serve the attach directly. // Kubelet will serve the attach directly.

View File

@ -24,6 +24,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/credentialprovider:go_default_library", "//pkg/credentialprovider:go_default_library",
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/events:go_default_library", "//pkg/kubelet/events:go_default_library",

View File

@ -49,6 +49,7 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/credentialprovider" "k8s.io/kubernetes/pkg/credentialprovider"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/pkg/kubelet/events"
@ -2068,14 +2069,14 @@ func newRktExitError(e error) error {
return e return e
} }
func (r *Runtime) AttachContainer(containerID kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (r *Runtime) AttachContainer(containerID kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
return fmt.Errorf("unimplemented") return fmt.Errorf("unimplemented")
} }
// Note: In rkt, the container ID is in the form of "UUID:appName", where UUID is // Note: In rkt, the container ID is in the form of "UUID:appName", where UUID is
// the rkt UUID, and appName is the container name. // the rkt UUID, and appName is the container name.
// TODO(yifan): If the rkt is using lkvm as the stage1 image, then this function will fail. // TODO(yifan): If the rkt is using lkvm as the stage1 image, then this function will fail.
func (r *Runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (r *Runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
glog.V(4).Infof("Rkt execing in container.") glog.V(4).Infof("Rkt execing in container.")
id, err := parseContainerID(containerID) id, err := parseContainerID(containerID)
@ -2096,7 +2097,7 @@ func (r *Runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []s
// make sure to close the stdout stream // make sure to close the stdout stream
defer stdout.Close() defer stdout.Close()
kubecontainer.HandleResizing(resize, func(size term.Size) { kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
term.SetSize(p.Fd(), size) term.SetSize(p.Fd(), size)
}) })

View File

@ -20,6 +20,7 @@ go_library(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/api/v1/validation:go_default_library", "//pkg/api/v1/validation:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm:go_default_library",
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/portforward:go_default_library",
@ -28,7 +29,6 @@ go_library(
"//pkg/kubelet/server/streaming:go_default_library", "//pkg/kubelet/server/streaming:go_default_library",
"//pkg/util/configz:go_default_library", "//pkg/util/configz:go_default_library",
"//pkg/util/limitwriter:go_default_library", "//pkg/util/limitwriter:go_default_library",
"//pkg/util/term:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//vendor:github.com/emicklei/go-restful", "//vendor:github.com/emicklei/go-restful",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
@ -40,6 +40,7 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/runtime", "//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema", "//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator", "//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
"//vendor:k8s.io/apiserver/pkg/authentication/user", "//vendor:k8s.io/apiserver/pkg/authentication/user",
@ -62,13 +63,13 @@ go_test(
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm:go_default_library",
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/container/testing:go_default_library",
"//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/portforward:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library", "//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/kubelet/server/stats:go_default_library", "//pkg/kubelet/server/stats:go_default_library",
"//pkg/util/term:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//vendor:github.com/google/cadvisor/info/v1", "//vendor:github.com/google/cadvisor/info/v1",
"//vendor:github.com/google/cadvisor/info/v2", "//vendor:github.com/google/cadvisor/info/v2",

View File

@ -11,7 +11,6 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"attach.go", "attach.go",
"constants.go",
"doc.go", "doc.go",
"exec.go", "exec.go",
"httpstream.go", "httpstream.go",
@ -20,14 +19,15 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/util/exec:go_default_library", "//pkg/util/exec:go_default_library",
"//pkg/util/term:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/httpstream", "//vendor:k8s.io/apimachinery/pkg/util/httpstream",
"//vendor:k8s.io/apimachinery/pkg/util/httpstream/spdy", "//vendor:k8s.io/apimachinery/pkg/util/httpstream/spdy",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/apiserver/pkg/server/httplog", "//vendor:k8s.io/apiserver/pkg/server/httplog",
"//vendor:k8s.io/apiserver/pkg/util/wsstream", "//vendor:k8s.io/apiserver/pkg/util/wsstream",

View File

@ -26,14 +26,14 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
) )
// Attacher knows how to attach to a running container in a pod. // Attacher knows how to attach to a running container in a pod.
type Attacher interface { type Attacher interface {
// AttachContainer attaches to the running container in the pod, copying data between in/out/err // AttachContainer attaches to the running container in the pod, copying data between in/out/err
// and the container's stdin/stdout/stderr. // 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 term.Size) error 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 // ServeAttach handles requests to attach to a container. After creating/receiving the required

View File

@ -25,21 +25,17 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
utilexec "k8s.io/kubernetes/pkg/util/exec" utilexec "k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/term"
)
const (
NonZeroExitCodeReason = metav1.StatusReason("NonZeroExitCode")
ExitCodeCauseType = metav1.CauseType("ExitCode")
) )
// Executor knows how to execute a command in a container in a pod. // Executor knows how to execute a command in a container in a pod.
type Executor interface { type Executor interface {
// ExecInContainer executes a command in a container in the pod, copying data // ExecInContainer executes a command in a container in the pod, copying data
// between in/out/err and the container's stdin/stdout/stderr. // 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 term.Size, timeout time.Duration) error 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 // ServeExec handles requests to execute a command in a container. After
@ -59,11 +55,11 @@ func ServeExec(w http.ResponseWriter, req *http.Request, executor Executor, podN
rc := exitErr.ExitStatus() rc := exitErr.ExitStatus()
ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{ ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure, Status: metav1.StatusFailure,
Reason: NonZeroExitCodeReason, Reason: remotecommandconsts.NonZeroExitCodeReason,
Details: &metav1.StatusDetails{ Details: &metav1.StatusDetails{
Causes: []metav1.StatusCause{ Causes: []metav1.StatusCause{
{ {
Type: ExitCodeCauseType, Type: remotecommandconsts.ExitCodeCauseType,
Message: fmt.Sprintf("%d", rc), Message: fmt.Sprintf("%d", rc),
}, },
}, },

View File

@ -28,10 +28,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/apimachinery/pkg/util/httpstream/spdy" "k8s.io/apimachinery/pkg/util/httpstream/spdy"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/util/wsstream" "k8s.io/apiserver/pkg/util/wsstream"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"github.com/golang/glog" "github.com/golang/glog"
) )
@ -78,7 +79,7 @@ type context struct {
stderrStream io.WriteCloser stderrStream io.WriteCloser
writeStatus func(status *apierrors.StatusError) error writeStatus func(status *apierrors.StatusError) error
resizeStream io.ReadCloser resizeStream io.ReadCloser
resizeChan chan term.Size resizeChan chan remotecommand.TerminalSize
tty bool tty bool
} }
@ -114,7 +115,7 @@ func createStreams(req *http.Request, w http.ResponseWriter, opts *Options, supp
} }
if ctx.resizeStream != nil { if ctx.resizeStream != nil {
ctx.resizeChan = make(chan term.Size) ctx.resizeChan = make(chan remotecommand.TerminalSize)
go handleResizeEvents(ctx.resizeStream, ctx.resizeChan) go handleResizeEvents(ctx.resizeStream, ctx.resizeChan)
} }
@ -148,16 +149,16 @@ func createHttpStreamStreams(req *http.Request, w http.ResponseWriter, opts *Opt
var handler protocolHandler var handler protocolHandler
switch protocol { switch protocol {
case StreamProtocolV4Name: case remotecommandconsts.StreamProtocolV4Name:
handler = &v4ProtocolHandler{} handler = &v4ProtocolHandler{}
case StreamProtocolV3Name: case remotecommandconsts.StreamProtocolV3Name:
handler = &v3ProtocolHandler{} handler = &v3ProtocolHandler{}
case StreamProtocolV2Name: case remotecommandconsts.StreamProtocolV2Name:
handler = &v2ProtocolHandler{} handler = &v2ProtocolHandler{}
case "": case "":
glog.V(4).Infof("Client did not request protocol negotiaion. Falling back to %q", StreamProtocolV1Name) glog.V(4).Infof("Client did not request protocol negotiaion. Falling back to %q", remotecommandconsts.StreamProtocolV1Name)
fallthrough fallthrough
case StreamProtocolV1Name: case remotecommandconsts.StreamProtocolV1Name:
handler = &v1ProtocolHandler{} handler = &v1ProtocolHandler{}
} }
@ -409,12 +410,12 @@ WaitForStreams:
// supportsTerminalResizing returns false because v1ProtocolHandler doesn't support it. // supportsTerminalResizing returns false because v1ProtocolHandler doesn't support it.
func (*v1ProtocolHandler) supportsTerminalResizing() bool { return false } func (*v1ProtocolHandler) supportsTerminalResizing() bool { return false }
func handleResizeEvents(stream io.Reader, channel chan<- term.Size) { func handleResizeEvents(stream io.Reader, channel chan<- remotecommand.TerminalSize) {
defer runtime.HandleCrash() defer runtime.HandleCrash()
decoder := json.NewDecoder(stream) decoder := json.NewDecoder(stream)
for { for {
size := term.Size{} size := remotecommand.TerminalSize{}
if err := decoder.Decode(&size); err != nil { if err := decoder.Decode(&size); err != nil {
break break
} }

View File

@ -41,6 +41,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
@ -50,15 +51,15 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/api/v1/validation" "k8s.io/kubernetes/pkg/api/v1/validation"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/cm"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/server/portforward" "k8s.io/kubernetes/pkg/kubelet/server/portforward"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/server/stats" "k8s.io/kubernetes/pkg/kubelet/server/stats"
"k8s.io/kubernetes/pkg/kubelet/server/streaming" "k8s.io/kubernetes/pkg/kubelet/server/streaming"
"k8s.io/kubernetes/pkg/util/configz" "k8s.io/kubernetes/pkg/util/configz"
"k8s.io/kubernetes/pkg/util/limitwriter" "k8s.io/kubernetes/pkg/util/limitwriter"
"k8s.io/kubernetes/pkg/util/term"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
@ -170,8 +171,8 @@ type HostInterface interface {
GetRunningPods() ([]*v1.Pod, error) GetRunningPods() ([]*v1.Pod, error)
GetPodByName(namespace, name string) (*v1.Pod, bool) GetPodByName(namespace, name string) (*v1.Pod, bool)
RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error) RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error)
ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error 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
AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error
GetKubeletContainerLogs(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error GetKubeletContainerLogs(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error
ServeLogs(w http.ResponseWriter, req *http.Request) ServeLogs(w http.ResponseWriter, req *http.Request)
PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error
@ -184,8 +185,8 @@ type HostInterface interface {
ImagesFsInfo() (cadvisorapiv2.FsInfo, error) ImagesFsInfo() (cadvisorapiv2.FsInfo, error)
RootFsInfo() (cadvisorapiv2.FsInfo, error) RootFsInfo() (cadvisorapiv2.FsInfo, error)
ListVolumesForPod(podUID types.UID) (map[string]volume.Volume, bool) ListVolumesForPod(podUID types.UID) (map[string]volume.Volume, bool)
GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommand.Options) (*url.URL, error) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error)
GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommand.Options) (*url.URL, error) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error)
GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error) GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error)
} }
@ -612,7 +613,7 @@ func getPortForwardRequestParams(req *restful.Request) portForwardRequestParams
// getAttach handles requests to attach to a container. // getAttach handles requests to attach to a container.
func (s *Server) getAttach(request *restful.Request, response *restful.Response) { func (s *Server) getAttach(request *restful.Request, response *restful.Response) {
params := getExecRequestParams(request) params := getExecRequestParams(request)
streamOpts, err := remotecommand.NewOptions(request.Request) streamOpts, err := remotecommandserver.NewOptions(request.Request)
if err != nil { if err != nil {
utilruntime.HandleError(err) utilruntime.HandleError(err)
response.WriteError(http.StatusBadRequest, err) response.WriteError(http.StatusBadRequest, err)
@ -635,7 +636,7 @@ func (s *Server) getAttach(request *restful.Request, response *restful.Response)
return return
} }
remotecommand.ServeAttach(response.ResponseWriter, remotecommandserver.ServeAttach(response.ResponseWriter,
request.Request, request.Request,
s.host, s.host,
podFullName, podFullName,
@ -643,14 +644,14 @@ func (s *Server) getAttach(request *restful.Request, response *restful.Response)
params.containerName, params.containerName,
streamOpts, streamOpts,
s.host.StreamingConnectionIdleTimeout(), s.host.StreamingConnectionIdleTimeout(),
remotecommand.DefaultStreamCreationTimeout, remotecommandconsts.DefaultStreamCreationTimeout,
remotecommand.SupportedStreamingProtocols) remotecommandconsts.SupportedStreamingProtocols)
} }
// getExec handles requests to run a command inside a container. // getExec handles requests to run a command inside a container.
func (s *Server) getExec(request *restful.Request, response *restful.Response) { func (s *Server) getExec(request *restful.Request, response *restful.Response) {
params := getExecRequestParams(request) params := getExecRequestParams(request)
streamOpts, err := remotecommand.NewOptions(request.Request) streamOpts, err := remotecommandserver.NewOptions(request.Request)
if err != nil { if err != nil {
utilruntime.HandleError(err) utilruntime.HandleError(err)
response.WriteError(http.StatusBadRequest, err) response.WriteError(http.StatusBadRequest, err)
@ -673,7 +674,7 @@ func (s *Server) getExec(request *restful.Request, response *restful.Response) {
return return
} }
remotecommand.ServeExec(response.ResponseWriter, remotecommandserver.ServeExec(response.ResponseWriter,
request.Request, request.Request,
s.host, s.host,
podFullName, podFullName,
@ -682,8 +683,8 @@ func (s *Server) getExec(request *restful.Request, response *restful.Response) {
params.cmd, params.cmd,
streamOpts, streamOpts,
s.host.StreamingConnectionIdleTimeout(), s.host.StreamingConnectionIdleTimeout(),
remotecommand.DefaultStreamCreationTimeout, remotecommandconsts.DefaultStreamCreationTimeout,
remotecommand.SupportedStreamingProtocols) remotecommandconsts.SupportedStreamingProtocols)
} }
// getRun handles requests to run a command inside a container. // getRun handles requests to run a command inside a container.
@ -757,7 +758,7 @@ func (s *Server) getPortForward(request *restful.Request, response *restful.Resp
params.podUID, params.podUID,
portForwardOptions, portForwardOptions,
s.host.StreamingConnectionIdleTimeout(), s.host.StreamingConnectionIdleTimeout(),
remotecommand.DefaultStreamCreationTimeout, remotecommandconsts.DefaultStreamCreationTimeout,
portforward.SupportedProtocols) portforward.SupportedProtocols)
} }

View File

@ -49,13 +49,13 @@ import (
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/cm"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
kubecontainertesting "k8s.io/kubernetes/pkg/kubelet/container/testing" kubecontainertesting "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/server/portforward" "k8s.io/kubernetes/pkg/kubelet/server/portforward"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/kubelet/server/stats" "k8s.io/kubernetes/pkg/kubelet/server/stats"
"k8s.io/kubernetes/pkg/util/term"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
@ -132,11 +132,11 @@ func (fk *fakeKubelet) RunInContainer(podFullName string, uid types.UID, contain
return fk.runFunc(podFullName, uid, containerName, cmd) return fk.runFunc(podFullName, uid, containerName, cmd)
} }
func (fk *fakeKubelet) ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (fk *fakeKubelet) 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 {
return fk.execFunc(name, uid, container, cmd, in, out, err, tty) return fk.execFunc(name, uid, container, cmd, in, out, err, tty)
} }
func (fk *fakeKubelet) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error { func (fk *fakeKubelet) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
return fk.attachFunc(name, uid, container, in, out, err, tty) return fk.attachFunc(name, uid, container, in, out, err, tty)
} }
@ -144,11 +144,11 @@ func (fk *fakeKubelet) PortForward(name string, uid types.UID, port int32, strea
return fk.portForwardFunc(name, uid, port, stream) return fk.portForwardFunc(name, uid, port, stream)
} }
func (fk *fakeKubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommand.Options) (*url.URL, error) { func (fk *fakeKubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) {
return fk.redirectURL, nil return fk.redirectURL, nil
} }
func (fk *fakeKubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommand.Options) (*url.URL, error) { func (fk *fakeKubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) {
return fk.redirectURL, nil return fk.redirectURL, nil
} }

View File

@ -17,14 +17,15 @@ go_library(
], ],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library", "//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/portforward:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library", "//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/util/term:go_default_library",
"//vendor:github.com/emicklei/go-restful", "//vendor:github.com/emicklei/go-restful",
"//vendor:google.golang.org/grpc", "//vendor:google.golang.org/grpc",
"//vendor:google.golang.org/grpc/codes", "//vendor:google.golang.org/grpc/codes",
"//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/client-go/util/clock", "//vendor:k8s.io/client-go/util/clock",
], ],
) )
@ -41,10 +42,9 @@ go_test(
"//pkg/client/unversioned/remotecommand:go_default_library", "//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/kubelet/api/v1alpha1/runtime:go_default_library", "//pkg/kubelet/api/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/portforward:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/util/term:go_default_library",
"//vendor:github.com/stretchr/testify/assert", "//vendor:github.com/stretchr/testify/assert",
"//vendor:github.com/stretchr/testify/require", "//vendor:github.com/stretchr/testify/require",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/client-go/pkg/api", "//vendor:k8s.io/client-go/pkg/api",
"//vendor:k8s.io/client-go/rest", "//vendor:k8s.io/client-go/rest",
"//vendor:k8s.io/client-go/util/clock", "//vendor:k8s.io/client-go/util/clock",

View File

@ -31,10 +31,11 @@ import (
restful "github.com/emicklei/go-restful" restful "github.com/emicklei/go-restful"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"k8s.io/kubernetes/pkg/kubelet/server/portforward" "k8s.io/kubernetes/pkg/kubelet/server/portforward"
"k8s.io/kubernetes/pkg/kubelet/server/remotecommand" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/util/term"
) )
// The library interface to serve the stream requests. // The library interface to serve the stream requests.
@ -59,8 +60,8 @@ type Server interface {
// The interface to execute the commands and provide the streams. // The interface to execute the commands and provide the streams.
type Runtime interface { type Runtime interface {
Exec(containerID string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error Exec(containerID string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error
Attach(containerID string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error Attach(containerID string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error
PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error
} }
@ -95,8 +96,8 @@ type Config struct {
// some fields like Addr must still be provided. // some fields like Addr must still be provided.
var DefaultConfig = Config{ var DefaultConfig = Config{
StreamIdleTimeout: 4 * time.Hour, StreamIdleTimeout: 4 * time.Hour,
StreamCreationTimeout: remotecommand.DefaultStreamCreationTimeout, StreamCreationTimeout: remotecommandconsts.DefaultStreamCreationTimeout,
SupportedRemoteCommandProtocols: remotecommand.SupportedStreamingProtocols, SupportedRemoteCommandProtocols: remotecommandconsts.SupportedStreamingProtocols,
SupportedPortForwardProtocols: portforward.SupportedProtocols, SupportedPortForwardProtocols: portforward.SupportedProtocols,
} }
@ -236,14 +237,14 @@ func (s *server) serveExec(req *restful.Request, resp *restful.Response) {
return return
} }
streamOpts := &remotecommand.Options{ streamOpts := &remotecommandserver.Options{
Stdin: exec.Stdin, Stdin: exec.Stdin,
Stdout: true, Stdout: true,
Stderr: !exec.Tty, Stderr: !exec.Tty,
TTY: exec.Tty, TTY: exec.Tty,
} }
remotecommand.ServeExec( remotecommandserver.ServeExec(
resp.ResponseWriter, resp.ResponseWriter,
req.Request, req.Request,
s.runtime, s.runtime,
@ -270,13 +271,13 @@ func (s *server) serveAttach(req *restful.Request, resp *restful.Response) {
return return
} }
streamOpts := &remotecommand.Options{ streamOpts := &remotecommandserver.Options{
Stdin: attach.Stdin, Stdin: attach.Stdin,
Stdout: true, Stdout: true,
Stderr: !attach.Tty, Stderr: !attach.Tty,
TTY: attach.Tty, TTY: attach.Tty,
} }
remotecommand.ServeAttach( remotecommandserver.ServeAttach(
resp.ResponseWriter, resp.ResponseWriter,
req.Request, req.Request,
s.runtime, s.runtime,
@ -326,15 +327,15 @@ type criAdapter struct {
Runtime Runtime
} }
var _ remotecommand.Executor = &criAdapter{} var _ remotecommandserver.Executor = &criAdapter{}
var _ remotecommand.Attacher = &criAdapter{} var _ remotecommandserver.Attacher = &criAdapter{}
var _ portforward.PortForwarder = &criAdapter{} var _ portforward.PortForwarder = &criAdapter{}
func (a *criAdapter) ExecInContainer(podName string, podUID types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size, timeout time.Duration) error { func (a *criAdapter) ExecInContainer(podName string, podUID types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
return a.Exec(container, cmd, in, out, err, tty, resize) return a.Exec(container, cmd, in, out, err, tty, resize)
} }
func (a *criAdapter) AttachContainer(podName string, podUID types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan term.Size) error { func (a *criAdapter) AttachContainer(podName string, podUID types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
return a.Attach(container, in, out, err, tty, resize) return a.Attach(container, in, out, err, tty, resize)
} }

View File

@ -30,13 +30,12 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
"k8s.io/client-go/pkg/api" "k8s.io/client-go/pkg/api"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand" "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
kubeletportforward "k8s.io/kubernetes/pkg/kubelet/server/portforward" kubeletportforward "k8s.io/kubernetes/pkg/kubelet/server/portforward"
kubeletremotecommand "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
"k8s.io/kubernetes/pkg/util/term"
) )
const ( const (
@ -302,12 +301,11 @@ func runRemoteCommandTest(t *testing.T, commandType string) {
require.NoError(t, err) require.NoError(t, err)
opts := remotecommand.StreamOptions{ opts := remotecommand.StreamOptions{
SupportedProtocols: kubeletremotecommand.SupportedStreamingProtocols, SupportedProtocols: remotecommandconsts.SupportedStreamingProtocols,
Stdin: stdinR, Stdin: stdinR,
Stdout: stdoutW, Stdout: stdoutW,
Stderr: stderrW, Stderr: stderrW,
Tty: false, Tty: false,
TerminalSizeQueue: nil,
} }
require.NoError(t, exec.Stream(opts)) require.NoError(t, exec.Stream(opts))
}() }()
@ -367,13 +365,13 @@ type fakeRuntime struct {
t *testing.T t *testing.T
} }
func (f *fakeRuntime) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (f *fakeRuntime) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
assert.Equal(f.t, testContainerID, containerID) assert.Equal(f.t, testContainerID, containerID)
doServerStreams(f.t, "exec", stdin, stdout, stderr) doServerStreams(f.t, "exec", stdin, stdout, stderr)
return nil return nil
} }
func (f *fakeRuntime) Attach(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error { func (f *fakeRuntime) Attach(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
assert.Equal(f.t, testContainerID, containerID) assert.Equal(f.t, testContainerID, containerID)
doServerStreams(f.t, "attach", stdin, stdout, stderr) doServerStreams(f.t, "attach", stdin, stdout, stderr)
return nil return nil

View File

@ -19,6 +19,7 @@ go_library(
], ],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/client/unversioned/remotecommand:go_default_library",
"//pkg/util/interrupt:go_default_library", "//pkg/util/interrupt:go_default_library",
"//vendor:github.com/docker/docker/pkg/term", "//vendor:github.com/docker/docker/pkg/term",
"//vendor:github.com/mitchellh/go-wordwrap", "//vendor:github.com/mitchellh/go-wordwrap",

View File

@ -21,17 +21,12 @@ import (
"github.com/docker/docker/pkg/term" "github.com/docker/docker/pkg/term"
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
) )
// Size represents the width and height of a terminal.
type Size struct {
Width uint16
Height uint16
}
// GetSize returns the current size of the user's terminal. If it isn't a terminal, // GetSize returns the current size of the user's terminal. If it isn't a terminal,
// nil is returned. // nil is returned.
func (t TTY) GetSize() *Size { func (t TTY) GetSize() *remotecommand.TerminalSize {
outFd, isTerminal := term.GetFdInfo(t.Out) outFd, isTerminal := term.GetFdInfo(t.Out)
if !isTerminal { if !isTerminal {
return nil return nil
@ -40,19 +35,19 @@ func (t TTY) GetSize() *Size {
} }
// GetSize returns the current size of the terminal associated with fd. // GetSize returns the current size of the terminal associated with fd.
func GetSize(fd uintptr) *Size { func GetSize(fd uintptr) *remotecommand.TerminalSize {
winsize, err := term.GetWinsize(fd) winsize, err := term.GetWinsize(fd)
if err != nil { if err != nil {
runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err)) runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err))
return nil return nil
} }
return &Size{Width: winsize.Width, Height: winsize.Height} return &remotecommand.TerminalSize{Width: winsize.Width, Height: winsize.Height}
} }
// MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with // MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with
// initialSizes, or nil if there's no TTY present. // initialSizes, or nil if there's no TTY present.
func (t *TTY) MonitorSize(initialSizes ...*Size) TerminalSizeQueue { func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecommand.TerminalSizeQueue {
outFd, isTerminal := term.GetFdInfo(t.Out) outFd, isTerminal := term.GetFdInfo(t.Out)
if !isTerminal { if !isTerminal {
return nil return nil
@ -62,7 +57,7 @@ func (t *TTY) MonitorSize(initialSizes ...*Size) TerminalSizeQueue {
t: *t, t: *t,
// make it buffered so we can send the initial terminal sizes without blocking, prior to starting // make it buffered so we can send the initial terminal sizes without blocking, prior to starting
// the streaming below // the streaming below
resizeChan: make(chan Size, len(initialSizes)), resizeChan: make(chan remotecommand.TerminalSize, len(initialSizes)),
stopResizing: make(chan struct{}), stopResizing: make(chan struct{}),
} }
@ -71,27 +66,20 @@ func (t *TTY) MonitorSize(initialSizes ...*Size) TerminalSizeQueue {
return t.sizeQueue return t.sizeQueue
} }
// TerminalSizeQueue is capable of returning terminal resize events as they occur. // sizeQueue implements remotecommand.TerminalSizeQueue
type TerminalSizeQueue interface {
// Next returns the new terminal size after the terminal has been resized. It returns nil when
// monitoring has been stopped.
Next() *Size
}
// sizeQueue implements TerminalSizeQueue
type sizeQueue struct { type sizeQueue struct {
t TTY t TTY
// resizeChan receives a Size each time the user's terminal is resized. // resizeChan receives a Size each time the user's terminal is resized.
resizeChan chan Size resizeChan chan remotecommand.TerminalSize
stopResizing chan struct{} stopResizing chan struct{}
} }
// make sure sizeQueue implements the TerminalSizeQueue interface // make sure sizeQueue implements the resize.TerminalSizeQueue interface
var _ TerminalSizeQueue = &sizeQueue{} var _ remotecommand.TerminalSizeQueue = &sizeQueue{}
// monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each // monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each
// new event, it sends the current terminal size to resizeChan. // new event, it sends the current terminal size to resizeChan.
func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*Size) { func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.TerminalSize) {
// send the initial sizes // send the initial sizes
for i := range initialSizes { for i := range initialSizes {
if initialSizes[i] != nil { if initialSizes[i] != nil {
@ -99,7 +87,7 @@ func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*Size) {
} }
} }
resizeEvents := make(chan Size, 1) resizeEvents := make(chan remotecommand.TerminalSize, 1)
monitorResizeEvents(outFd, resizeEvents, s.stopResizing) monitorResizeEvents(outFd, resizeEvents, s.stopResizing)
@ -130,7 +118,7 @@ func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*Size) {
// Next returns the new terminal size after the terminal has been resized. It returns nil when // Next returns the new terminal size after the terminal has been resized. It returns nil when
// monitoring has been stopped. // monitoring has been stopped.
func (s *sizeQueue) Next() *Size { func (s *sizeQueue) Next() *remotecommand.TerminalSize {
size, ok := <-s.resizeChan size, ok := <-s.resizeChan
if !ok { if !ok {
return nil return nil

View File

@ -24,12 +24,13 @@ import (
"syscall" "syscall"
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
) )
// monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the // monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the
// terminal has resized). After receiving a SIGWINCH, this gets the terminal size and tries to send // terminal has resized). After receiving a SIGWINCH, this gets the terminal size and tries to send
// it to the resizeEvents channel. The goroutine stops when the stop channel is closed. // it to the resizeEvents channel. The goroutine stops when the stop channel is closed.
func monitorResizeEvents(fd uintptr, resizeEvents chan<- Size, stop chan struct{}) { func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) {
go func() { go func() {
defer runtime.HandleCrash() defer runtime.HandleCrash()

View File

@ -20,9 +20,10 @@ package term
import ( import (
"github.com/docker/docker/pkg/term" "github.com/docker/docker/pkg/term"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
) )
// SetSize sets the terminal size associated with fd. // SetSize sets the terminal size associated with fd.
func SetSize(fd uintptr, size Size) error { func SetSize(fd uintptr, size remotecommand.TerminalSize) error {
return term.SetWinsize(fd, &term.Winsize{Height: size.Height, Width: size.Width}) return term.SetWinsize(fd, &term.Winsize{Height: size.Height, Width: size.Width})
} }

View File

@ -16,7 +16,11 @@ limitations under the License.
package remotecommand package remotecommand
import "time" import (
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const ( const (
DefaultStreamCreationTimeout = 30 * time.Second DefaultStreamCreationTimeout = 30 * time.Second
@ -41,6 +45,9 @@ const (
// attachment/execution. It is the 4th version of the subprotocol and // attachment/execution. It is the 4th version of the subprotocol and
// adds support for exit codes. // adds support for exit codes.
StreamProtocolV4Name = "v4.channel.k8s.io" StreamProtocolV4Name = "v4.channel.k8s.io"
NonZeroExitCodeReason = metav1.StatusReason("NonZeroExitCode")
ExitCodeCauseType = metav1.CauseType("ExitCode")
) )
var SupportedStreamingProtocols = []string{StreamProtocolV4Name, StreamProtocolV3Name, StreamProtocolV2Name, StreamProtocolV1Name} var SupportedStreamingProtocols = []string{StreamProtocolV4Name, StreamProtocolV3Name, StreamProtocolV2Name, StreamProtocolV1Name}

View File

@ -68,7 +68,6 @@ go_library(
"//pkg/kubelet/api/v1alpha1/stats:go_default_library", "//pkg/kubelet/api/v1alpha1/stats:go_default_library",
"//pkg/kubelet/events:go_default_library", "//pkg/kubelet/events:go_default_library",
"//pkg/kubelet/metrics:go_default_library", "//pkg/kubelet/metrics:go_default_library",
"//pkg/kubelet/server/remotecommand:go_default_library",
"//pkg/kubelet/server/stats:go_default_library", "//pkg/kubelet/server/stats:go_default_library",
"//pkg/kubelet/sysctl:go_default_library", "//pkg/kubelet/sysctl:go_default_library",
"//pkg/kubelet/util/format:go_default_library", "//pkg/kubelet/util/format:go_default_library",
@ -117,6 +116,7 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/util/intstr", "//vendor:k8s.io/apimachinery/pkg/util/intstr",
"//vendor:k8s.io/apimachinery/pkg/util/net", "//vendor:k8s.io/apimachinery/pkg/util/net",
"//vendor:k8s.io/apimachinery/pkg/util/rand", "//vendor:k8s.io/apimachinery/pkg/util/rand",
"//vendor:k8s.io/apimachinery/pkg/util/remotecommand",
"//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/sets", "//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/apimachinery/pkg/util/uuid", "//vendor:k8s.io/apimachinery/pkg/util/uuid",

View File

@ -23,11 +23,11 @@ import (
"strings" "strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
remocommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand" "k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
@ -140,7 +140,7 @@ func execute(method string, url *url.URL, config *restclient.Config, stdin io.Re
return err return err
} }
return exec.Stream(remotecommand.StreamOptions{ return exec.Stream(remotecommand.StreamOptions{
SupportedProtocols: remotecommandserver.SupportedStreamingProtocols, SupportedProtocols: remocommandconsts.SupportedStreamingProtocols,
Stdin: stdin, Stdin: stdin,
Stdout: stdout, Stdout: stdout,
Stderr: stderr, Stderr: stderr,

7
vendor/BUILD vendored
View File

@ -16429,3 +16429,10 @@ go_test(
"//vendor:k8s.io/client-go/kubernetes/fake", "//vendor:k8s.io/client-go/kubernetes/fake",
], ],
) )
go_library(
name = "k8s.io/apimachinery/pkg/util/remotecommand",
srcs = ["k8s.io/apimachinery/pkg/util/remotecommand/constants.go"],
tags = ["automanaged"],
deps = ["//vendor:k8s.io/apimachinery/pkg/apis/meta/v1"],
)