Bläddra i källkod

changed not found errors to 404, added inspect, wait and diff

Victor Vieux 12 år sedan
förälder
incheckning
1e357c6969
3 ändrade filer med 135 tillägg och 58 borttagningar
  1. 86 8
      api.go
  2. 4 0
      api_params.go
  3. 45 50
      commands.go

+ 86 - 8
api.go

@@ -42,12 +42,46 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 				return
 				return
 			}
 			}
 		} else {
 		} else {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 			return
 			return
 		}
 		}
 		w.WriteHeader(200)
 		w.WriteHeader(200)
 	})
 	})
 
 
+	r.Path("/images/{name:.*}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		log.Println(r.Method, r.RequestURI)
+		vars := mux.Vars(r)
+		name := vars["name"]
+
+		if image, err := rtime.repositories.LookupImage(name); err == nil && image != nil {
+			b, err := json.Marshal(image)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+			} else {
+				w.Write(b)
+			}
+			return
+		}
+		http.Error(w, "No such image: "+name, http.StatusNotFound)
+	})
+
+	r.Path("/containers/{name:.*}").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 {
+			b, err := json.Marshal(container)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+			} else {
+				w.Write(b)
+			}
+			return
+		}
+		http.Error(w, "No such container: "+name, http.StatusNotFound)
+	})
+
 	r.Path("/images").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 	r.Path("/images").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		log.Println(r.Method, r.RequestURI)
 		log.Println(r.Method, r.RequestURI)
 		if err := r.ParseForm(); err != nil {
 		if err := r.ParseForm(); err != nil {
@@ -211,7 +245,33 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 			}
 			}
 
 
 		} else {
 		} else {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
+		}
+	})
+
+	r.Path("/containers/{name:.*}/changes").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 {
+			changes, err := container.Changes()
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+			var changesStr []string
+			for _, name := range changes {
+				changesStr = append(changesStr, name.String())
+			}
+			b, err := json.Marshal(changesStr)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+			} else {
+				w.Write(b)
+			}
+		} else {
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 		}
 		}
 	})
 	})
 
 
@@ -225,7 +285,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 		name := vars["name"]
 		name := vars["name"]
 
 
 		if container := rtime.Get(name); container == nil {
 		if container := rtime.Get(name); container == nil {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 			return
 			return
 		} else {
 		} else {
 			if frontend, exists := container.NetworkSettings.PortMapping[privatePort]; !exists {
 			if frontend, exists := container.NetworkSettings.PortMapping[privatePort]; !exists {
@@ -423,7 +483,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 				return
 				return
 			}
 			}
 		} else {
 		} else {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 			return
 			return
 		}
 		}
 		w.WriteHeader(200)
 		w.WriteHeader(200)
@@ -439,7 +499,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 				return
 				return
 			}
 			}
 		} else {
 		} else {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 			return
 			return
 		}
 		}
 		w.WriteHeader(200)
 		w.WriteHeader(200)
@@ -452,7 +512,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 
 
 		img, err := rtime.repositories.LookupImage(name)
 		img, err := rtime.repositories.LookupImage(name)
 		if err != nil {
 		if err != nil {
-			http.Error(w, "No such image: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such image: "+name, http.StatusNotFound)
 			return
 			return
 		} else {
 		} else {
 			if err := rtime.graph.Delete(img.Id); err != nil {
 			if err := rtime.graph.Delete(img.Id); err != nil {
@@ -473,7 +533,7 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 				return
 				return
 			}
 			}
 		} else {
 		} else {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 			return
 			return
 		}
 		}
 		w.WriteHeader(200)
 		w.WriteHeader(200)
@@ -489,11 +549,29 @@ func ListenAndServe(addr string, rtime *Runtime) error {
 				return
 				return
 			}
 			}
 		} else {
 		} else {
-			http.Error(w, "No such container: "+name, http.StatusInternalServerError)
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
 			return
 			return
 		}
 		}
 		w.WriteHeader(200)
 		w.WriteHeader(200)
 	})
 	})
 
 
+	r.Path("/containers/{name:.*}/wait").Methods("POST").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 {
+			b, err := json.Marshal(ApiWait{container.Wait()})
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+			} else {
+				w.Write(b)
+			}
+			return
+		} else {
+			http.Error(w, "No such container: "+name, http.StatusNotFound)
+			return
+		}
+	})
+
 	return http.ListenAndServe(addr, r)
 	return http.ListenAndServe(addr, r)
 }
 }

+ 4 - 0
api_params.go

@@ -44,3 +44,7 @@ type ApiVersion struct {
 	GitCommit           string
 	GitCommit           string
 	MemoryLimitDisabled bool
 	MemoryLimitDisabled bool
 }
 }
+
+type ApiWait struct {
+	StatusCode int
+}

+ 45 - 50
commands.go

@@ -26,8 +26,10 @@ var (
 func ParseCommands(args []string) error {
 func ParseCommands(args []string) error {
 
 
 	cmds := map[string]func(args []string) error{
 	cmds := map[string]func(args []string) error{
+		"diff":    CmdDiff,
 		"images":  CmdImages,
 		"images":  CmdImages,
 		"info":    CmdInfo,
 		"info":    CmdInfo,
+		"inspect": CmdInspect,
 		"history": CmdHistory,
 		"history": CmdHistory,
 		"kill":    CmdKill,
 		"kill":    CmdKill,
 		"logs":    CmdLogs,
 		"logs":    CmdLogs,
@@ -42,6 +44,7 @@ func ParseCommands(args []string) error {
 		"start":   CmdStart,
 		"start":   CmdStart,
 		"stop":    CmdStop,
 		"stop":    CmdStop,
 		"version": CmdVersion,
 		"version": CmdVersion,
+		"wait":    CmdWait,
 	}
 	}
 
 
 	if len(args) > 0 {
 	if len(args) > 0 {
@@ -60,13 +63,13 @@ func cmdHelp(args []string) error {
 	for _, cmd := range [][]string{
 	for _, cmd := range [][]string{
 		//		{"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"},
 		{"info", "Display system-wide information"},
 		{"info", "Display system-wide information"},
-		//		{"inspect", "Return low-level information on a container"},
+		{"inspect", "Return low-level information on a container/image"},
 		{"kill", "Kill a running container"},
 		{"kill", "Kill a running container"},
 		//		{"login", "Register or Login to the docker registry server"},
 		//		{"login", "Register or Login to the docker registry server"},
 		{"logs", "Fetch the logs of a container"},
 		{"logs", "Fetch the logs of a container"},
@@ -82,7 +85,7 @@ func cmdHelp(args []string) error {
 		{"stop", "Stop a running container"},
 		{"stop", "Stop a running container"},
 		{"tag", "Tag an image into a repository"},
 		{"tag", "Tag an image into a repository"},
 		{"version", "Show the docker version information"},
 		{"version", "Show the docker version information"},
-		//		{"wait", "Block until a container stops, then print its exit code"},
+		{"wait", "Block until a container stops, then print its exit code"},
 	} {
 	} {
 		help += fmt.Sprintf("    %-10.10s%s\n", cmd[0], cmd[1])
 		help += fmt.Sprintf("    %-10.10s%s\n", cmd[0], cmd[1])
 	}
 	}
@@ -190,10 +193,9 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ..
 }
 }
 */
 */
 
 
-/*
 // 'docker wait': block until a container stops
 // 'docker wait': block until a container stops
-func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
-	cmd := rcli.Subcmd(stdout, "wait", "CONTAINER [CONTAINER...]", "Block until a container stops, then print its exit code.")
+func CmdWait(args []string) error {
+	cmd := Subcmd("wait", "CONTAINER [CONTAINER...]", "Block until a container stops, then print its exit code.")
 	if err := cmd.Parse(args); err != nil {
 	if err := cmd.Parse(args); err != nil {
 		return nil
 		return nil
 	}
 	}
@@ -202,15 +204,20 @@ func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string
 		return nil
 		return nil
 	}
 	}
 	for _, name := range cmd.Args() {
 	for _, name := range cmd.Args() {
-		if container := srv.runtime.Get(name); container != nil {
-			fmt.Fprintln(stdout, container.Wait())
+		body, err := call("POST", "/containers/"+name+"/wait")
+		if err != nil {
+			fmt.Printf("%s", err)
 		} else {
 		} else {
-			return fmt.Errorf("No such container: %s", name)
+			var out ApiWait
+			err = json.Unmarshal(body, &out)
+			if err != nil {
+				return err
+			}
+			fmt.Println(out.StatusCode)
 		}
 		}
 	}
 	}
 	return nil
 	return nil
 }
 }
-*/
 
 
 // 'docker version': show version information
 // 'docker version': show version information
 func CmdVersion(args []string) error {
 func CmdVersion(args []string) error {
@@ -334,42 +341,31 @@ func CmdStart(args []string) error {
 	return nil
 	return nil
 }
 }
 
 
-/*
-func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
-	cmd := rcli.Subcmd(stdout, "inspect", "CONTAINER", "Return low-level information on a container")
+func CmdInspect(args []string) error {
+	cmd := Subcmd("inspect", "CONTAINER|IMAGE", "Return low-level information on a container/image")
 	if err := cmd.Parse(args); err != nil {
 	if err := cmd.Parse(args); err != nil {
 		return nil
 		return nil
 	}
 	}
-	if cmd.NArg() < 1 {
+	if cmd.NArg() != 1 {
 		cmd.Usage()
 		cmd.Usage()
 		return nil
 		return nil
 	}
 	}
-	name := cmd.Arg(0)
 	var obj interface{}
 	var obj interface{}
-	if container := srv.runtime.Get(name); container != nil {
-		obj = container
-	} else if image, err := srv.runtime.repositories.LookupImage(name); err == nil && image != nil {
-		obj = image
-	} else {
-		// No output means the object does not exist
-		// (easier to script since stdout and stderr are not differentiated atm)
-		return nil
-	}
-	data, err := json.Marshal(obj)
+	var err error
+	obj, err = call("GET", "/containers/"+cmd.Arg(0))
 	if err != nil {
 	if err != nil {
-		return err
-	}
-	indented := new(bytes.Buffer)
-	if err = json.Indent(indented, data, "", "    "); err != nil {
-		return err
+		obj, err = call("GET", "/images/"+cmd.Arg(0))
+		if err != nil {
+			return err
+		}
 	}
 	}
-	if _, err := io.Copy(stdout, indented); err != nil {
+	b, err := json.MarshalIndent(obj, "", "    ")
+	if err != nil {
 		return err
 		return err
 	}
 	}
-	stdout.Write([]byte{'\n'})
+	fmt.Printf("%s\n", b)
 	return nil
 	return nil
 }
 }
-*/
 
 
 func CmdPort(args []string) error {
 func CmdPort(args []string) error {
 	cmd := Subcmd("port", "CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT")
 	cmd := Subcmd("port", "CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT")
@@ -778,32 +774,31 @@ func (srv *Server) CmdExport(stdin io.ReadCloser, stdout io.Writer, args ...stri
 }
 }
 */
 */
 
 
-/*
-func (srv *Server) CmdDiff(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
-	cmd := rcli.Subcmd(stdout,
-		"diff", "CONTAINER",
-		"Inspect changes on a container's filesystem")
+func CmdDiff(args []string) error {
+	cmd := Subcmd("diff", "CONTAINER", "Inspect changes on a container's filesystem")
 	if err := cmd.Parse(args); err != nil {
 	if err := cmd.Parse(args); err != nil {
 		return nil
 		return nil
 	}
 	}
-	if cmd.NArg() < 1 {
+	if cmd.NArg() != 1 {
 		cmd.Usage()
 		cmd.Usage()
 		return nil
 		return nil
 	}
 	}
-	if container := srv.runtime.Get(cmd.Arg(0)); container == nil {
-		return fmt.Errorf("No such container")
-	} else {
-		changes, err := container.Changes()
-		if err != nil {
-			return err
-		}
-		for _, change := range changes {
-			fmt.Fprintln(stdout, change.String())
-		}
+
+	body, err := call("GET", "/containers/"+cmd.Arg(0)+"/changes")
+	if err != nil {
+		return err
+	}
+
+	var changes []string
+	err = json.Unmarshal(body, &changes)
+	if err != nil {
+		return err
+	}
+	for _, change := range changes {
+		fmt.Println(change)
 	}
 	}
 	return nil
 	return nil
 }
 }
-*/
 
 
 func CmdLogs(args []string) error {
 func CmdLogs(args []string) error {
 	cmd := Subcmd("logs", "CONTAINER", "Fetch the logs of a container")
 	cmd := Subcmd("logs", "CONTAINER", "Fetch the logs of a container")