Browse code

move attach to a job

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)

Victor Vieux authored on 2014/01/09 07:05:05
Showing 4 changed files
... ...
@@ -4,26 +4,26 @@
4 4
 TODO    "/events":                              getEvents,              N
5 5
 ok      "/info":                                getInfo,                1
6 6
 ok      "/version":                             getVersion,             1
7
-ok     "/images/json":                         getImagesJSON,          N
7
+ok      "/images/json":                         getImagesJSON,          N
8 8
 ok      "/images/viz":                          getImagesViz,           0                       yes
9
-#3615   "/images/search":                       getImagesSearch,        N
10
-ok    "/images/{name:.*}/get":                getImagesGet,           0
11
-ok    "/images/{name:.*}/history":            getImagesHistory,       N
12
-TODO    "/images/{name:.*}/json":               getImagesByName,        1
9
+ok      "/images/search":                       getImagesSearch,        N
10
+ok      "/images/{name:.*}/get":                getImagesGet,           0
11
+ok      "/images/{name:.*}/history":            getImagesHistory,       N
12
+...     "/images/{name:.*}/json":               getImagesByName,        1
13 13
 TODO    "/containers/ps":                       getContainersJSON,      N
14 14
 TODO    "/containers/json":                     getContainersJSON,      1
15 15
 ok      "/containers/{name:.*}/export":         getContainersExport,    0
16
-...     "/containers/{name:.*}/changes":        getContainersChanges,   N
17
-TODO    "/containers/{name:.*}/json":           getContainersByName,    1
16
+#3616   "/containers/{name:.*}/changes":        getContainersChanges,   N
17
+...     "/containers/{name:.*}/json":           getContainersByName,    1
18 18
 TODO    "/containers/{name:.*}/top":            getContainersTop,       N
19
-#3512   "/containers/{name:.*}/attach/ws":      wsContainersAttach,     0                                       yes
19
+ok      "/containers/{name:.*}/attach/ws":      wsContainersAttach,     0                                       yes
20 20
 
21 21
 **POST**
22 22
 TODO    "/auth":                                postAuth,               0                       yes
23 23
 ok      "/commit":                              postCommit,             0
24 24
 TODO    "/build":                               postBuild,              0                       yes
25 25
 TODO    "/images/create":                       postImagesCreate,       N                       yes             yes (pull)
26
-#3559   "/images/{name:.*}/insert":             postImagesInsert,       N                       yes             yes
26
+ok      "/images/{name:.*}/insert":             postImagesInsert,       N                       yes             yes
27 27
 TODO    "/images/load":                         postImagesLoad,         1                                       yes (stdin)
28 28
 TODO    "/images/{name:.*}/push":               postImagesPush,         N                                       yes
29 29
 ok      "/images/{name:.*}/tag":                postImagesTag,          0
... ...
@@ -34,8 +34,8 @@ ok      "/containers/{name:.*}/start":          postContainersStart,    0
34 34
 ok      "/containers/{name:.*}/stop":           postContainersStop,     0
35 35
 ok      "/containers/{name:.*}/wait":           postContainersWait,     0
36 36
 ok      "/containers/{name:.*}/resize":         postContainersResize,   0
37
-#3512   "/containers/{name:.*}/attach":         postContainersAttach,   0                                       yes
38
-#3560   "/containers/{name:.*}/copy":           postContainersCopy,     0                       yes
37
+ok      "/containers/{name:.*}/attach":         postContainersAttach,   0                                       yes
38
+ok   "/containers/{name:.*}/copy":           postContainersCopy,     0                       yes
39 39
 
40 40
 **DELETE**
41 41
 ok      "/containers/{name:.*}":                deleteContainers,       0
... ...
@@ -769,33 +769,11 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
769 769
 	if err := parseForm(r); err != nil {
770 770
 		return err
771 771
 	}
772
-	logs, err := getBoolParam(r.Form.Get("logs"))
773
-	if err != nil {
774
-		return err
775
-	}
776
-	stream, err := getBoolParam(r.Form.Get("stream"))
777
-	if err != nil {
778
-		return err
779
-	}
780
-	stdin, err := getBoolParam(r.Form.Get("stdin"))
781
-	if err != nil {
782
-		return err
783
-	}
784
-	stdout, err := getBoolParam(r.Form.Get("stdout"))
785
-	if err != nil {
786
-		return err
787
-	}
788
-	stderr, err := getBoolParam(r.Form.Get("stderr"))
789
-	if err != nil {
790
-		return err
791
-	}
792
-
793 772
 	if vars == nil {
794 773
 		return fmt.Errorf("Missing parameter")
795 774
 	}
796
-	name := vars["name"]
797 775
 
798
-	c, err := srv.ContainerInspect(name)
776
+	c, err := srv.ContainerInspect(vars["name"])
799 777
 	if err != nil {
800 778
 		return err
801 779
 	}
... ...
@@ -830,51 +808,46 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
830 830
 		errStream = outStream
831 831
 	}
832 832
 
833
-	if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, inStream, outStream, errStream); err != nil {
833
+	job := srv.Eng.Job("attach", vars["name"])
834
+	job.Setenv("logs", r.Form.Get("logs"))
835
+	job.Setenv("stream", r.Form.Get("stream"))
836
+	job.Setenv("stdin", r.Form.Get("stdin"))
837
+	job.Setenv("stdout", r.Form.Get("stdout"))
838
+	job.Setenv("stderr", r.Form.Get("stderr"))
839
+	job.Stdin.Add(inStream)
840
+	job.Stdout.Add(outStream)
841
+	job.Stderr.Add(errStream)
842
+	if err := job.Run(); err != nil {
834 843
 		fmt.Fprintf(outStream, "Error: %s\n", err)
844
+
835 845
 	}
836 846
 	return nil
837 847
 }
838 848
 
839 849
 func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
840
-
841 850
 	if err := parseForm(r); err != nil {
842 851
 		return err
843 852
 	}
844
-	logs, err := getBoolParam(r.Form.Get("logs"))
845
-	if err != nil {
846
-		return err
847
-	}
848
-	stream, err := getBoolParam(r.Form.Get("stream"))
849
-	if err != nil {
850
-		return err
851
-	}
852
-	stdin, err := getBoolParam(r.Form.Get("stdin"))
853
-	if err != nil {
854
-		return err
855
-	}
856
-	stdout, err := getBoolParam(r.Form.Get("stdout"))
857
-	if err != nil {
858
-		return err
859
-	}
860
-	stderr, err := getBoolParam(r.Form.Get("stderr"))
861
-	if err != nil {
862
-		return err
863
-	}
864
-
865 853
 	if vars == nil {
866 854
 		return fmt.Errorf("Missing parameter")
867 855
 	}
868
-	name := vars["name"]
869 856
 
870
-	if _, err := srv.ContainerInspect(name); err != nil {
857
+	if _, err := srv.ContainerInspect(vars["name"]); err != nil {
871 858
 		return err
872 859
 	}
873 860
 
874 861
 	h := websocket.Handler(func(ws *websocket.Conn) {
875 862
 		defer ws.Close()
876
-
877
-		if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, ws, ws, ws); err != nil {
863
+		job := srv.Eng.Job("attach", vars["name"])
864
+		job.Setenv("logs", r.Form.Get("logs"))
865
+		job.Setenv("stream", r.Form.Get("stream"))
866
+		job.Setenv("stdin", r.Form.Get("stdin"))
867
+		job.Setenv("stdout", r.Form.Get("stdout"))
868
+		job.Setenv("stderr", r.Form.Get("stderr"))
869
+		job.Stdin.Add(ws)
870
+		job.Stdout.Add(ws)
871
+		job.Stderr.Add(ws)
872
+		if err := job.Run(); err != nil {
878 873
 			utils.Errorf("Error: %s", err)
879 874
 		}
880 875
 	})
... ...
@@ -141,6 +141,17 @@ func (i *Input) Read(p []byte) (n int, err error) {
141 141
 	return i.src.Read(p)
142 142
 }
143 143
 
144
+// Closes the src
145
+// Not thread safe on purpose
146
+func (i *Input) Close() error {
147
+	if i.src != nil {
148
+		if closer, ok := i.src.(io.WriteCloser); ok {
149
+			return closer.Close()
150
+		}
151
+	}
152
+	return nil
153
+}
154
+
144 155
 // Add attaches a new source to the input.
145 156
 // Add can only be called once per input. Subsequent calls will
146 157
 // return an error.
... ...
@@ -147,6 +147,10 @@ func jobInitApi(job *engine.Job) engine.Status {
147 147
 		job.Error(err)
148 148
 		return engine.StatusErr
149 149
 	}
150
+	if err := job.Eng.Register("attach", srv.ContainerAttach); err != nil {
151
+		job.Error(err)
152
+		return engine.StatusErr
153
+	}
150 154
 	return engine.StatusOK
151 155
 }
152 156
 
... ...
@@ -1980,10 +1984,25 @@ func (srv *Server) ContainerResize(job *engine.Job) engine.Status {
1980 1980
 	return engine.StatusErr
1981 1981
 }
1982 1982
 
1983
-func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, stderr bool, inStream io.ReadCloser, outStream, errStream io.Writer) error {
1983
+func (srv *Server) ContainerAttach(job *engine.Job) engine.Status {
1984
+	if len(job.Args) != 1 {
1985
+		job.Errorf("Usage: %s CONTAINER\n", job.Name)
1986
+		return engine.StatusErr
1987
+	}
1988
+
1989
+	var (
1990
+		name   = job.Args[0]
1991
+		logs   = job.GetenvBool("logs")
1992
+		stream = job.GetenvBool("stream")
1993
+		stdin  = job.GetenvBool("stdin")
1994
+		stdout = job.GetenvBool("stdout")
1995
+		stderr = job.GetenvBool("stderr")
1996
+	)
1997
+
1984 1998
 	container := srv.runtime.Get(name)
1985 1999
 	if container == nil {
1986
-		return fmt.Errorf("No such container: %s", name)
2000
+		job.Errorf("No such container: %s", name)
2001
+		return engine.StatusErr
1987 2002
 	}
1988 2003
 
1989 2004
 	//logs
... ...
@@ -1991,12 +2010,12 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
1991 1991
 		cLog, err := container.ReadLog("json")
1992 1992
 		if err != nil && os.IsNotExist(err) {
1993 1993
 			// Legacy logs
1994
-			utils.Errorf("Old logs format")
1994
+			utils.Debugf("Old logs format")
1995 1995
 			if stdout {
1996 1996
 				cLog, err := container.ReadLog("stdout")
1997 1997
 				if err != nil {
1998 1998
 					utils.Errorf("Error reading logs (stdout): %s", err)
1999
-				} else if _, err := io.Copy(outStream, cLog); err != nil {
1999
+				} else if _, err := io.Copy(job.Stdout, cLog); err != nil {
2000 2000
 					utils.Errorf("Error streaming logs (stdout): %s", err)
2001 2001
 				}
2002 2002
 			}
... ...
@@ -2004,7 +2023,7 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
2004 2004
 				cLog, err := container.ReadLog("stderr")
2005 2005
 				if err != nil {
2006 2006
 					utils.Errorf("Error reading logs (stderr): %s", err)
2007
-				} else if _, err := io.Copy(errStream, cLog); err != nil {
2007
+				} else if _, err := io.Copy(job.Stderr, cLog); err != nil {
2008 2008
 					utils.Errorf("Error streaming logs (stderr): %s", err)
2009 2009
 				}
2010 2010
 			}
... ...
@@ -2022,10 +2041,10 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
2022 2022
 					break
2023 2023
 				}
2024 2024
 				if l.Stream == "stdout" && stdout {
2025
-					fmt.Fprintf(outStream, "%s", l.Log)
2025
+					fmt.Fprintf(job.Stdout, "%s", l.Log)
2026 2026
 				}
2027 2027
 				if l.Stream == "stderr" && stderr {
2028
-					fmt.Fprintf(errStream, "%s", l.Log)
2028
+					fmt.Fprintf(job.Stderr, "%s", l.Log)
2029 2029
 				}
2030 2030
 			}
2031 2031
 		}
... ...
@@ -2034,7 +2053,8 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
2034 2034
 	//stream
2035 2035
 	if stream {
2036 2036
 		if container.State.IsGhost() {
2037
-			return fmt.Errorf("Impossible to attach to a ghost container")
2037
+			job.Errorf("Impossible to attach to a ghost container")
2038
+			return engine.StatusErr
2038 2039
 		}
2039 2040
 
2040 2041
 		var (
... ...
@@ -2048,16 +2068,16 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
2048 2048
 			go func() {
2049 2049
 				defer w.Close()
2050 2050
 				defer utils.Debugf("Closing buffered stdin pipe")
2051
-				io.Copy(w, inStream)
2051
+				io.Copy(w, job.Stdin)
2052 2052
 			}()
2053 2053
 			cStdin = r
2054
-			cStdinCloser = inStream
2054
+			cStdinCloser = job.Stdin
2055 2055
 		}
2056 2056
 		if stdout {
2057
-			cStdout = outStream
2057
+			cStdout = job.Stdout
2058 2058
 		}
2059 2059
 		if stderr {
2060
-			cStderr = errStream
2060
+			cStderr = job.Stderr
2061 2061
 		}
2062 2062
 
2063 2063
 		<-container.Attach(cStdin, cStdinCloser, cStdout, cStderr)
... ...
@@ -2068,7 +2088,7 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
2068 2068
 			container.Wait()
2069 2069
 		}
2070 2070
 	}
2071
-	return nil
2071
+	return engine.StatusOK
2072 2072
 }
2073 2073
 
2074 2074
 func (srv *Server) ContainerInspect(name string) (*Container, error) {