Victor Vieux 12 gadi atpakaļ
vecāks
revīzija
e5104a4cb4
3 mainītis faili ar 60 papildinājumiem un 12 dzēšanām
  1. 28 10
      api.go
  2. 11 2
      commands.go
  3. 21 0
      utils.go

+ 28 - 10
api.go

@@ -451,14 +451,14 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 
 		fmt.Fprintln(file, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n")
 		if rtime.graph.LookupRemoteImage(name, rtime.authConfig) {
-                        if err := rtime.graph.PullImage(file, name, rtime.authConfig); err != nil {
-                                fmt.Fprintln(file, "Error: "+err.Error())
-                        }
-                        return
-                }
-                if err := rtime.graph.PullRepository(file, name, "", rtime.repositories, rtime.authConfig); err != nil {
-                        fmt.Fprintln(file, "Error: "+err.Error())
-                }
+			if err := rtime.graph.PullImage(file, name, rtime.authConfig); err != nil {
+				fmt.Fprintln(file, "Error: "+err.Error())
+			}
+			return
+		}
+		if err := rtime.graph.PullRepository(file, name, "", rtime.repositories, rtime.authConfig); err != nil {
+			fmt.Fprintln(file, "Error: "+err.Error())
+		}
 	})
 
 	r.Path("/containers").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -482,6 +482,18 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 		}
 		defer file.Close()
 
+		if config.Tty {
+			oldState, err := SetRawTerminal()
+			if err != nil {
+				if os.Getenv("DEBUG") != "" {
+					log.Printf("Can't set the terminal in raw mode: %s", err)
+				}
+			} else {
+				defer RestoreTerminal(oldState)
+			}
+
+		}
+
 		fmt.Fprintln(file, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n")
 		container, err := rtime.Create(&config)
 		if err != nil {
@@ -493,7 +505,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 						fmt.Fprintln(file, "Error: "+err.Error())
 						return
 					}
-				} else  if err := rtime.graph.PullRepository(file, config.Image, "", rtime.repositories, rtime.authConfig); err != nil {
+				} else if err := rtime.graph.PullRepository(file, config.Image, "", rtime.repositories, rtime.authConfig); err != nil {
 					fmt.Fprintln(file, "Error: "+err.Error())
 					return
 				}
@@ -523,7 +535,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 			cStdout = file
 		}
 		if config.AttachStderr {
-			cStderr = file // FIXME: rcli can't differentiate stdout from stderr                                                         
+			cStderr = file // FIXME: api can't differentiate stdout from stderr
 		}
 
 		attachErr := container.Attach(cStdin, file, cStdout, cStderr)
@@ -538,6 +550,12 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 		Debugf("Waiting for attach to return\n")
 		<-attachErr
 		// Expecting I/O pipe error, discarding
+
+		// If we are in stdinonce mode, wait for the process to end
+		// otherwise, simply return
+		if config.StdinOnce && !config.Tty {
+			container.Wait()
+		}
 	})
 
 	r.Path("/containers/{name:.*}/attach").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

+ 11 - 2
commands.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"flag"
 	"fmt"
+	"github.com/dotcloud/docker/term"
 	"io"
 	"io/ioutil"
 	"net"
@@ -967,7 +968,7 @@ func call(method, path string) ([]byte, error) {
 
 }
 
-func callStream(method, path string, data interface{}, isTerminal bool) error {
+func callStream(method, path string, data interface{}, setRawTerminal bool) error {
 	var body io.Reader
 	if data != nil {
 		buf, err := json.Marshal(data)
@@ -996,6 +997,14 @@ func callStream(method, path string, data interface{}, isTerminal bool) error {
 	rwc, _ := clientconn.Hijack()
 	defer rwc.Close()
 
+	if setRawTerminal && term.IsTerminal(int(os.Stdin.Fd())) && os.Getenv("NORAW") == "" {
+		if oldState, err := SetRawTerminal(); err != nil {
+			return err
+		} else {
+			defer RestoreTerminal(oldState)
+		}
+	}
+
 	receiveStdout := Go(func() error {
 		_, err := io.Copy(os.Stdout, rwc)
 		return err
@@ -1009,7 +1018,7 @@ func callStream(method, path string, data interface{}, isTerminal bool) error {
 	if err := <-receiveStdout; err != nil {
 		return err
 	}
-	if isTerminal {
+	if !term.IsTerminal(int(os.Stdin.Fd())) {
 		if err := <-sendStdin; err != nil {
 			return err
 		}

+ 21 - 0
utils.go

@@ -5,12 +5,14 @@ import (
 	"errors"
 	"fmt"
 	"github.com/dotcloud/docker/rcli"
+	"github.com/dotcloud/docker/term"
 	"index/suffixarray"
 	"io"
 	"io/ioutil"
 	"net/http"
 	"os"
 	"os/exec"
+	"os/signal"
 	"path/filepath"
 	"runtime"
 	"strings"
@@ -384,3 +386,22 @@ func CopyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error)
 	}
 	return written, err
 }
+
+func SetRawTerminal() (*term.State, error) {
+	oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
+	if err != nil {
+		return nil, err
+	}
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, os.Interrupt)
+	go func() {
+		_ = <-c
+		term.Restore(int(os.Stdin.Fd()), oldState)
+		os.Exit(0)
+	}()
+	return oldState, err
+}
+
+func RestoreTerminal(state *term.State) {
+	term.Restore(int(os.Stdin.Fd()), state)
+}