Browse Source

Replace os.File with io.ReadCloser and io.Writer

Guillaume J. Charmes 12 years ago
parent
commit
57cfe72e8c
2 changed files with 81 additions and 126 deletions
  1. 42 87
      api.go
  2. 39 39
      server.go

+ 42 - 87
api.go

@@ -1,35 +1,26 @@
 package docker
 
 import (
-	_ "bytes"
 	"encoding/json"
 	"fmt"
 	"github.com/dotcloud/docker/auth"
 	"github.com/gorilla/mux"
 	"github.com/shin-/cookiejar"
+	"io"
 	"log"
-	"net"
 	"net/http"
-	"os"
 	"strconv"
 	"strings"
 )
 
-func hijackServer(w http.ResponseWriter) (*os.File, net.Conn, error) {
-	rwc, _, err := w.(http.Hijacker).Hijack()
+func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
+	conn, _, err := w.(http.Hijacker).Hijack()
 	if err != nil {
 		return nil, nil, err
 	}
-
-	file, err := rwc.(*net.TCPConn).File()
-	if err != nil {
-		return nil, rwc, err
-	}
-
 	// Flush the options to make sure the client sets the raw mode
-	rwc.Write([]byte{})
-
-	return file, rwc, nil
+	conn.Write([]byte{})
+	return conn, conn, nil
 }
 
 func httpError(w http.ResponseWriter, err error) {
@@ -106,19 +97,14 @@ func getContainersExport(srv *Server, w http.ResponseWriter, r *http.Request) ([
 	vars := mux.Vars(r)
 	name := vars["name"]
 
-	file, rwc, err := hijackServer(w)
-	if file != nil {
-		defer file.Close()
-	}
-	if rwc != nil {
-		defer rwc.Close()
-	}
+	in, out, err := hijackServer(w)
 	if err != nil {
+		defer in.Close()
 		return nil, err
 	}
-	fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
-	if err := srv.ContainerExport(name, file); err != nil {
-		fmt.Fprintf(file, "Error: %s\n", err)
+	fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+	if err := srv.ContainerExport(name, out); err != nil {
+		fmt.Fprintf(out, "Error: %s\n", err)
 		return nil, err
 	}
 	return nil, nil
@@ -131,19 +117,14 @@ func getImages(srv *Server, w http.ResponseWriter, r *http.Request) ([]byte, err
 
 	viz := r.Form.Get("viz") == "1"
 	if viz {
-		file, rwc, err := hijackServer(w)
-		if file != nil {
-			defer file.Close()
-		}
-		if rwc != nil {
-			defer rwc.Close()
-		}
+		in, out, err := hijackServer(w)
 		if err != nil {
+			defer in.Close()
 			return nil, err
 		}
-		fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
-		if err := srv.ImagesViz(file); err != nil {
-			fmt.Fprintf(file, "Error: %s\n", err)
+		fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+		if err := srv.ImagesViz(out); err != nil {
+			fmt.Fprintf(out, "Error: %s\n", err)
 		}
 		return nil, nil
 	}
@@ -288,26 +269,21 @@ func postImages(srv *Server, w http.ResponseWriter, r *http.Request) ([]byte, er
 	repo := r.Form.Get("repo")
 	tag := r.Form.Get("tag")
 
-	file, rwc, err := hijackServer(w)
-	if file != nil {
-		defer file.Close()
-	}
-	if rwc != nil {
-		defer rwc.Close()
-	}
+	in, out, err := hijackServer(w)
 	if err != nil {
+		defer in.Close()
 		return nil, err
 	}
-	fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+	fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
 	if image != "" { //pull
 		registry := r.Form.Get("registry")
-		if err := srv.ImagePull(image, tag, registry, file); err != nil {
-			fmt.Fprintf(file, "Error: %s\n", err)
+		if err := srv.ImagePull(image, tag, registry, out); err != nil {
+			fmt.Fprintf(out, "Error: %s\n", err)
 			return nil, err
 		}
 	} else { //import
-		if err := srv.ImageImport(src, repo, tag, file); err != nil {
-			fmt.Fprintf(file, "Error: %s\n", err)
+		if err := srv.ImageImport(src, repo, tag, in, out); err != nil {
+			fmt.Fprintf(out, "Error: %s\n", err)
 			return nil, err
 		}
 	}
@@ -341,19 +317,14 @@ func postImagesInsert(srv *Server, w http.ResponseWriter, r *http.Request) ([]by
 	vars := mux.Vars(r)
 	name := vars["name"]
 
-	file, rwc, err := hijackServer(w)
-	if file != nil {
-		defer file.Close()
-	}
-	if rwc != nil {
-		defer rwc.Close()
-	}
+	in, out, err := hijackServer(w)
 	if err != nil {
+		defer in.Close()
 		return nil, err
 	}
-	fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
-	if err := srv.ImageInsert(name, url, path, file); err != nil {
-		fmt.Fprintf(file, "Error: %s\n", err)
+	fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+	if err := srv.ImageInsert(name, url, path, out); err != nil {
+		fmt.Fprintf(out, "Error: %s\n", err)
 		return nil, err
 	}
 	return nil, nil
@@ -369,39 +340,28 @@ func postImagesPush(srv *Server, w http.ResponseWriter, r *http.Request) ([]byte
 	vars := mux.Vars(r)
 	name := vars["name"]
 
-	file, rwc, err := hijackServer(w)
-	if file != nil {
-		defer file.Close()
-	}
-	if rwc != nil {
-		defer rwc.Close()
-	}
+	in, out, err := hijackServer(w)
 	if err != nil {
+		defer in.Close()
 		return nil, err
 	}
-	fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
-	if err := srv.ImagePush(name, registry, file); err != nil {
-		fmt.Fprintln(file, "Error: $s\n", err)
+	fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+	if err := srv.ImagePush(name, registry, out); err != nil {
+		fmt.Fprintln(out, "Error: %s\n", err)
 		return nil, err
 	}
 	return nil, nil
 }
 
 func postBuild(srv *Server, w http.ResponseWriter, r *http.Request) ([]byte, error) {
-
-	file, rwc, err := hijackServer(w)
-	if file != nil {
-		defer file.Close()
-	}
-	if rwc != nil {
-		defer rwc.Close()
-	}
+	in, out, err := hijackServer(w)
 	if err != nil {
+		defer in.Close()
 		return nil, err
 	}
-	fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
-	if err := srv.ImageCreateFormFile(file); err != nil {
-		fmt.Fprintln(file, "Error: %s\n", err)
+	fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+	if err := srv.ImageCreateFromFile(in, out); err != nil {
+		fmt.Fprintln(out, "Error: %s\n", err)
 		return nil, err
 	}
 	return nil, nil
@@ -532,20 +492,15 @@ func postContainersAttach(srv *Server, w http.ResponseWriter, r *http.Request) (
 	vars := mux.Vars(r)
 	name := vars["name"]
 
-	file, rwc, err := hijackServer(w)
-	if file != nil {
-		defer file.Close()
-	}
-	if rwc != nil {
-		defer rwc.Close()
-	}
+	in, out, err := hijackServer(w)
 	if err != nil {
+		defer in.Close()
 		return nil, err
 	}
 
-	fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
-	if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, file); err != nil {
-		fmt.Fprintf(file, "Error: %s\n", err)
+	fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n")
+	if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil {
+		fmt.Fprintf(out, "Error: %s\n", err)
 		return nil, err
 	}
 	return nil, nil

+ 39 - 39
server.go

@@ -26,7 +26,7 @@ func (srv *Server) ContainerKill(name string) error {
 	return nil
 }
 
-func (srv *Server) ContainerExport(name string, file *os.File) error {
+func (srv *Server) ContainerExport(name string, out io.Writer) error {
 	if container := srv.runtime.Get(name); container != nil {
 
 		data, err := container.Export()
@@ -35,7 +35,7 @@ func (srv *Server) ContainerExport(name string, file *os.File) error {
 		}
 
 		// Stream the entire contents of the container (basically a volatile snapshot)
-		if _, err := io.Copy(file, data); err != nil {
+		if _, err := io.Copy(out, data); err != nil {
 			return err
 		}
 		return nil
@@ -62,13 +62,13 @@ func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) {
 	return outs, nil
 }
 
-func (srv *Server) ImageInsert(name, url, path string, stdout *os.File) error {
+func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error {
 	img, err := srv.runtime.repositories.LookupImage(name)
 	if err != nil {
 		return err
 	}
 
-	file, err := Download(url, stdout)
+	file, err := Download(url, out)
 	if err != nil {
 		return err
 	}
@@ -85,7 +85,7 @@ func (srv *Server) ImageInsert(name, url, path string, stdout *os.File) error {
 		return err
 	}
 
-	if err := c.Inject(ProgressReader(file.Body, int(file.ContentLength), stdout, "Downloading %v/%v (%v)"), path); err != nil {
+	if err := c.Inject(ProgressReader(file.Body, int(file.ContentLength), out, "Downloading %v/%v (%v)"), path); err != nil {
 		return err
 	}
 	// FIXME: Handle custom repo, tag comment, author
@@ -93,29 +93,31 @@ func (srv *Server) ImageInsert(name, url, path string, stdout *os.File) error {
 	if err != nil {
 		return err
 	}
-	fmt.Fprintf(stdout, "%s\n", img.Id)
+	fmt.Fprintf(out, "%s\n", img.Id)
 	return nil
 }
 
-func (srv *Server) ImagesViz(file *os.File) error {
+func (srv *Server) ImagesViz(out io.Writer) error {
 	images, _ := srv.runtime.graph.All()
 	if images == nil {
 		return nil
 	}
 
-	fmt.Fprintf(file, "digraph docker {\n")
+	fmt.Fprintf(out, "digraph docker {\n")
 
-	var parentImage *Image
-	var err error
+	var (
+		parentImage *Image
+		err         error
+	)
 	for _, image := range images {
 		parentImage, err = image.GetParent()
 		if err != nil {
 			return fmt.Errorf("Error while getting parent image: %v", err)
 		}
 		if parentImage != nil {
-			fmt.Fprintf(file, "  \"%s\" -> \"%s\"\n", parentImage.ShortId(), image.ShortId())
+			fmt.Fprintf(out, "  \"%s\" -> \"%s\"\n", parentImage.ShortId(), image.ShortId())
 		} else {
-			fmt.Fprintf(file, "  base -> \"%s\" [style=invis]\n", image.ShortId())
+			fmt.Fprintf(out, "  base -> \"%s\" [style=invis]\n", image.ShortId())
 		}
 	}
 
@@ -128,11 +130,9 @@ func (srv *Server) ImagesViz(file *os.File) error {
 	}
 
 	for id, repos := range reporefs {
-		fmt.Fprintf(file, "  \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n", id, id, strings.Join(repos, "\\n"))
+		fmt.Fprintf(out, "  \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n", id, id, strings.Join(repos, "\\n"))
 	}
-
-	fmt.Fprintf(file, "  base [style=invisible]\n")
-	fmt.Fprintf(file, "}\n")
+	fmt.Fprintf(out, "  base [style=invisible]\n}\n")
 	return nil
 }
 
@@ -299,26 +299,26 @@ func (srv *Server) ContainerTag(name, repo, tag string, force bool) error {
 	return nil
 }
 
-func (srv *Server) ImagePull(name, tag, registry string, file *os.File) error {
+func (srv *Server) ImagePull(name, tag, registry string, out io.Writer) error {
 	if registry != "" {
-		if err := srv.runtime.graph.PullImage(file, name, registry, nil); err != nil {
+		if err := srv.runtime.graph.PullImage(out, name, registry, nil); err != nil {
 			return err
 		}
 		return nil
 	}
-	if err := srv.runtime.graph.PullRepository(file, name, tag, srv.runtime.repositories, srv.runtime.authConfig); err != nil {
+	if err := srv.runtime.graph.PullRepository(out, name, tag, srv.runtime.repositories, srv.runtime.authConfig); err != nil {
 		return err
 	}
 	return nil
 }
 
-func (srv *Server) ImagePush(name, registry string, file *os.File) error {
+func (srv *Server) ImagePush(name, registry string, out io.Writer) error {
 	img, err := srv.runtime.graph.Get(name)
 	if err != nil {
 		Debugf("The push refers to a repository [%s] (len: %d)\n", name, len(srv.runtime.repositories.Repositories[name]))
 		// If it fails, try to get the repository
 		if localRepo, exists := srv.runtime.repositories.Repositories[name]; exists {
-			if err := srv.runtime.graph.PushRepository(file, name, localRepo, srv.runtime.authConfig); err != nil {
+			if err := srv.runtime.graph.PushRepository(out, name, localRepo, srv.runtime.authConfig); err != nil {
 				return err
 			}
 			return nil
@@ -326,37 +326,37 @@ func (srv *Server) ImagePush(name, registry string, file *os.File) error {
 
 		return err
 	}
-	err = srv.runtime.graph.PushImage(file, img, registry, nil)
+	err = srv.runtime.graph.PushImage(out, img, registry, nil)
 	if err != nil {
 		return err
 	}
 	return nil
 }
 
-func (srv *Server) ImageImport(src, repo, tag string, file *os.File) error {
+func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer) error {
 	var archive io.Reader
 	var resp *http.Response
 
 	if src == "-" {
-		archive = file
+		archive = in
 	} else {
 		u, err := url.Parse(src)
 		if err != nil {
-			fmt.Fprintf(file, "Error: %s\n", err)
+			fmt.Fprintf(out, "Error: %s\n", err)
 		}
 		if u.Scheme == "" {
 			u.Scheme = "http"
 			u.Host = src
 			u.Path = ""
 		}
-		fmt.Fprintln(file, "Downloading from", u)
+		fmt.Fprintln(out, "Downloading from", u)
 		// Download with curl (pretty progress bar)
 		// If curl is not available, fallback to http.Get()
-		resp, err = Download(u.String(), file)
+		resp, err = Download(u.String(), out)
 		if err != nil {
 			return err
 		}
-		archive = ProgressReader(resp.Body, int(resp.ContentLength), file, "Importing %v/%v (%v)")
+		archive = ProgressReader(resp.Body, int(resp.ContentLength), out, "Importing %v/%v (%v)")
 	}
 	img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
 	if err != nil {
@@ -368,7 +368,7 @@ func (srv *Server) ImageImport(src, repo, tag string, file *os.File) error {
 			return err
 		}
 	}
-	fmt.Fprintln(file, img.ShortId())
+	fmt.Fprintln(out, img.ShortId())
 	return nil
 }
 
@@ -397,12 +397,12 @@ func (srv *Server) ContainerCreate(config Config) (string, bool, bool, error) {
 	return container.ShortId(), memoryW, swapW, nil
 }
 
-func (srv *Server) ImageCreateFormFile(file *os.File) error {
-	img, err := NewBuilder(srv.runtime).Build(file, file)
+func (srv *Server) ImageCreateFromFile(dockerfile io.Reader, out io.Writer) error {
+	img, err := NewBuilder(srv.runtime).Build(dockerfile, out)
 	if err != nil {
 		return err
 	}
-	fmt.Fprintf(file, "%s\n", img.ShortId())
+	fmt.Fprintf(out, "%s\n", img.ShortId())
 	return nil
 }
 
@@ -496,7 +496,7 @@ func (srv *Server) ContainerWait(name string) (int, error) {
 	return 0, fmt.Errorf("No such container: %s", name)
 }
 
-func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, stderr bool, file *os.File) error {
+func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, stderr bool, in io.ReadCloser, out io.Writer) error {
 	if container := srv.runtime.Get(name); container != nil {
 		//logs
 		if logs {
@@ -504,7 +504,7 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
 				cLog, err := container.ReadLog("stdout")
 				if err != nil {
 					Debugf(err.Error())
-				} else if _, err := io.Copy(file, cLog); err != nil {
+				} else if _, err := io.Copy(out, cLog); err != nil {
 					Debugf(err.Error())
 				}
 			}
@@ -512,7 +512,7 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
 				cLog, err := container.ReadLog("stderr")
 				if err != nil {
 					Debugf(err.Error())
-				} else if _, err := io.Copy(file, cLog); err != nil {
+				} else if _, err := io.Copy(out, cLog); err != nil {
 					Debugf(err.Error())
 				}
 			}
@@ -535,16 +535,16 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
 				go func() {
 					defer w.Close()
 					defer Debugf("Closing buffered stdin pipe")
-					io.Copy(w, file)
+					io.Copy(w, in)
 				}()
 				cStdin = r
-				cStdinCloser = file
+				cStdinCloser = in
 			}
 			if stdout {
-				cStdout = file
+				cStdout = out
 			}
 			if stderr {
-				cStderr = file
+				cStderr = out
 			}
 
 			<-container.Attach(cStdin, cStdinCloser, cStdout, cStderr)