Victor Vieux 12 سال پیش
والد
کامیت
c7bbe7ca79
2فایلهای تغییر یافته به همراه60 افزوده شده و 19 حذف شده
  1. 37 0
      api.go
  2. 23 19
      commands.go

+ 37 - 0
api.go

@@ -65,6 +65,43 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 		http.Error(w, "No such image: "+name, http.StatusNotFound)
 		http.Error(w, "No such image: "+name, http.StatusNotFound)
 	})
 	})
 
 
+	r.Path("/containers/{name:.*}/export").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		log.Println(r.Method, r.RequestURI)
+		vars := mux.Vars(r)
+		name := vars["name"]
+
+		if container := rtime.Get(name); container != nil {
+
+			data, err := container.Export()
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+			conn, _, err := w.(http.Hijacker).Hijack()
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+			defer conn.Close()
+			file, err := conn.(*net.TCPConn).File()
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+			defer file.Close()
+
+			fmt.Fprintln(file, "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\n\r\n")
+			// Stream the entire contents of the container (basically a volatile snapshot)
+			if _, err := io.Copy(file, data); err != nil {
+				fmt.Fprintln(file, "Error: "+err.Error())
+				return
+			}
+		} else {
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
+		}
+
+	})
+
 	r.Path("/containers/{name:.*}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 	r.Path("/containers/{name:.*}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		log.Println(r.Method, r.RequestURI)
 		log.Println(r.Method, r.RequestURI)
 		vars := mux.Vars(r)
 		vars := mux.Vars(r)

+ 23 - 19
commands.go

@@ -28,6 +28,7 @@ func ParseCommands(args []string) error {
 	cmds := map[string]func(args []string) error{
 	cmds := map[string]func(args []string) error{
 		"commit":  CmdCommit,
 		"commit":  CmdCommit,
 		"diff":    CmdDiff,
 		"diff":    CmdDiff,
+		"export":  CmdExport,
 		"images":  CmdImages,
 		"images":  CmdImages,
 		"info":    CmdInfo,
 		"info":    CmdInfo,
 		"inspect": CmdInspect,
 		"inspect": CmdInspect,
@@ -65,7 +66,7 @@ func cmdHelp(args []string) error {
 		//		{"attach", "Attach to a running container"},
 		//		{"attach", "Attach to a running container"},
 		{"commit", "Create a new image from a container's changes"},
 		{"commit", "Create a new image from a container's changes"},
 		{"diff", "Inspect changes on a container's filesystem"},
 		{"diff", "Inspect changes on a container's filesystem"},
-		//		{"export", "Stream the contents of a container as a tar archive"},
+		{"export", "Stream the contents of a container as a tar archive"},
 		{"history", "Show the history of an image"},
 		{"history", "Show the history of an image"},
 		{"images", "List images"},
 		{"images", "List images"},
 		//		{"import", "Create a new filesystem image from the contents of a tarball"},
 		//		{"import", "Create a new filesystem image from the contents of a tarball"},
@@ -759,29 +760,22 @@ func CmdCommit(args []string) error {
 	return nil
 	return nil
 }
 }
 
 
-/*
-func (srv *Server) CmdExport(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
-	cmd := rcli.Subcmd(stdout,
-		"export", "CONTAINER",
-		"Export the contents of a filesystem as a tar archive")
+func CmdExport(args []string) error {
+	cmd := Subcmd("export", "CONTAINER", "Export the contents of a filesystem as a tar archive")
 	if err := cmd.Parse(args); err != nil {
 	if err := cmd.Parse(args); err != nil {
 		return nil
 		return nil
 	}
 	}
-	name := cmd.Arg(0)
-	if container := srv.runtime.Get(name); container != nil {
-		data, err := container.Export()
-		if err != nil {
-			return err
-		}
-		// Stream the entire contents of the container (basically a volatile snapshot)
-		if _, err := io.Copy(stdout, data); err != nil {
-			return err
-		}
+
+	if cmd.NArg() != 1 {
+		cmd.Usage()
 		return nil
 		return nil
 	}
 	}
-	return fmt.Errorf("No such container: %s", name)
+
+	if err := callStream("GET", "/containers/"+cmd.Arg(0)+"/export", nil, false); err != nil {
+		return err
+	}
+	return nil
 }
 }
-*/
 
 
 func CmdDiff(args []string) error {
 func CmdDiff(args []string) error {
 	cmd := Subcmd("diff", "CONTAINER", "Inspect changes on a container's filesystem")
 	cmd := Subcmd("diff", "CONTAINER", "Inspect changes on a container's filesystem")
@@ -1010,8 +1004,18 @@ func callStream(method, path string, data interface{}, isTerminal bool) error {
 		return err
 		return err
 	}
 	}
 	clientconn := httputil.NewClientConn(dial, nil)
 	clientconn := httputil.NewClientConn(dial, nil)
-	clientconn.Do(req)
+	resp, err := clientconn.Do(req)
 	defer clientconn.Close()
 	defer clientconn.Close()
+	if err != nil {
+		return err
+	}
+	if resp.StatusCode != 200 {
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			return err
+		}
+		return fmt.Errorf("error: %s", body)
+	}
 
 
 	rwc, _ := clientconn.Hijack()
 	rwc, _ := clientconn.Hijack()
 	defer rwc.Close()
 	defer rwc.Close()