Merge pull request #6574 from ncdc/exec-portforward-no-command-pipes

Don't use command pipes for exec/port forward
pull/6/head
Clayton Coleman 2015-04-10 12:07:21 -04:00
commit fce3e5a2bb
1 changed files with 18 additions and 37 deletions

View File

@ -221,6 +221,11 @@ func (d *dockerContainerCommandRunner) RunInContainer(containerID string, cmd []
// - should we support nsenter in a container, running with elevated privs and --pid=host? // - should we support nsenter in a container, running with elevated privs and --pid=host?
// - use strong type for containerId // - use strong type for containerId
func (d *dockerContainerCommandRunner) ExecInContainer(containerId string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error { func (d *dockerContainerCommandRunner) ExecInContainer(containerId string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error {
nsenter, err := exec.LookPath("nsenter")
if err != nil {
return fmt.Errorf("exec unavailable - unable to locate nsenter")
}
container, err := d.client.InspectContainer(containerId) container, err := d.client.InspectContainer(containerId)
if err != nil { if err != nil {
return err return err
@ -237,8 +242,7 @@ func (d *dockerContainerCommandRunner) ExecInContainer(containerId string, cmd [
args = append(args, fmt.Sprintf("HOSTNAME=%s", container.Config.Hostname)) args = append(args, fmt.Sprintf("HOSTNAME=%s", container.Config.Hostname))
args = append(args, container.Config.Env...) args = append(args, container.Config.Env...)
args = append(args, cmd...) args = append(args, cmd...)
command := exec.Command("nsenter", args...) command := exec.Command(nsenter, args...)
// TODO use exec.LookPath
if tty { if tty {
p, err := StartPty(command) p, err := StartPty(command)
if err != nil { if err != nil {
@ -259,39 +263,24 @@ func (d *dockerContainerCommandRunner) ExecInContainer(containerId string, cmd [
return command.Wait() return command.Wait()
} else { } else {
cp := func(dst io.WriteCloser, src io.Reader, closeDst bool) {
defer func() {
if closeDst {
dst.Close()
}
}()
io.Copy(dst, src)
}
if stdin != nil { if stdin != nil {
inPipe, err := command.StdinPipe() // Use an os.Pipe here as it returns true *os.File objects.
// This way, if you run 'kubectl exec -p <pod> -i bash' (no tty) and type 'exit',
// the call below to command.Run() can unblock because its Stdin is the read half
// of the pipe.
r, w, err := os.Pipe()
if err != nil { if err != nil {
return err return err
} }
go func() { go io.Copy(w, stdin)
cp(inPipe, stdin, false)
inPipe.Close()
}()
}
command.Stdin = r
}
if stdout != nil { if stdout != nil {
outPipe, err := command.StdoutPipe() command.Stdout = stdout
if err != nil {
return err
} }
go cp(stdout, outPipe, true)
}
if stderr != nil { if stderr != nil {
errPipe, err := command.StderrPipe() command.Stderr = stderr
if err != nil {
return err
}
go cp(stderr, errPipe, true)
} }
return command.Run() return command.Run()
@ -325,16 +314,8 @@ func (d *dockerContainerCommandRunner) PortForward(pod *kubecontainer.Pod, port
args := []string{"-t", fmt.Sprintf("%d", containerPid), "-n", "socat", "-", fmt.Sprintf("TCP4:localhost:%d", port)} args := []string{"-t", fmt.Sprintf("%d", containerPid), "-n", "socat", "-", fmt.Sprintf("TCP4:localhost:%d", port)}
// TODO use exec.LookPath // TODO use exec.LookPath
command := exec.Command("nsenter", args...) command := exec.Command("nsenter", args...)
in, err := command.StdinPipe() command.Stdin = stream
if err != nil { command.Stdout = stream
return err
}
out, err := command.StdoutPipe()
if err != nil {
return err
}
go io.Copy(in, stream)
go io.Copy(stream, out)
return command.Run() return command.Run()
} }