Parcourir la source

add ps args to docker top

Victor Vieux il y a 12 ans
Parent
commit
cfec1c3e1b
5 fichiers modifiés avec 51 ajouts et 36 suppressions
  1. 5 1
      api.go
  2. 2 4
      api_params.go
  3. 18 9
      api_test.go
  4. 11 6
      commands.go
  5. 15 16
      server.go

+ 5 - 1
api.go

@@ -255,8 +255,12 @@ func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *ht
 	if vars == nil {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 		return fmt.Errorf("Missing parameter")
 	}
 	}
+	if err := parseForm(r); err != nil {
+		return err
+	}
 	name := vars["name"]
 	name := vars["name"]
-	procsStr, err := srv.ContainerTop(name)
+	ps_args := r.Form.Get("ps_args")
+	procsStr, err := srv.ContainerTop(name, ps_args)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 2 - 4
api_params.go

@@ -27,10 +27,8 @@ type APIInfo struct {
 }
 }
 
 
 type APITop struct {
 type APITop struct {
-	PID  string
-	Tty  string
-	Time string
-	Cmd  string
+	Titles    []string
+	Processes [][]string
 }
 }
 
 
 type APIRmi struct {
 type APIRmi struct {

+ 18 - 9
api_test.go

@@ -444,24 +444,33 @@ func TestGetContainersTop(t *testing.T) {
 	}
 	}
 
 
 	r := httptest.NewRecorder()
 	r := httptest.NewRecorder()
-	if err := getContainersTop(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
+	req, err := http.NewRequest("GET", "/"+container.ID+"/top?ps_args=u", bytes.NewReader([]byte{}))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := getContainersTop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	procs := []APITop{}
+	procs := APITop{}
 	if err := json.Unmarshal(r.Body.Bytes(), &procs); err != nil {
 	if err := json.Unmarshal(r.Body.Bytes(), &procs); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	if len(procs) != 2 {
-		t.Fatalf("Expected 2 processes, found %d.", len(procs))
+	if len(procs.Titles) != 11 {
+		t.Fatalf("Expected 11 titles, found %d.", len(procs.Titles))
 	}
 	}
-
-	if procs[0].Cmd != "sh" && procs[0].Cmd != "busybox" {
-		t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[0].Cmd)
+	if procs.Titles[0] != "USER" || procs.Titles[10] != "COMMAND" {
+		t.Fatalf("Expected Titles[0] to be USER and Titles[10] to be COMMAND, found %s and %s.", procs.Titles[0], procs.Titles[10])
 	}
 	}
 
 
-	if procs[1].Cmd != "sh" && procs[1].Cmd != "busybox" {
-		t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[1].Cmd)
+	if len(procs.Processes) != 2 {
+		t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes))
+	}
+	if procs.Processes[0][10] != "/bin/sh" && procs.Processes[0][10] != "sleep" {
+		t.Fatalf("Expected `sleep` or `/bin/sh`, found %s.", procs.Processes[0][10])
+	}
+	if procs.Processes[1][10] != "/bin/sh" && procs.Processes[1][10] != "sleep" {
+		t.Fatalf("Expected `sleep` or `/bin/sh`, found %s.", procs.Processes[1][10])
 	}
 	}
 }
 }
 
 

+ 11 - 6
commands.go

@@ -585,23 +585,28 @@ func (cli *DockerCli) CmdTop(args ...string) error {
 	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() == 0 {
 		cmd.Usage()
 		cmd.Usage()
 		return nil
 		return nil
 	}
 	}
-	body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top", nil)
+	val := url.Values{}
+	if cmd.NArg() > 1 {
+		val.Set("ps_args", strings.Join(cmd.Args()[1:], " "))
+	}
+
+	body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	var procs []APITop
+	procs := APITop{}
 	err = json.Unmarshal(body, &procs)
 	err = json.Unmarshal(body, &procs)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
 	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
-	fmt.Fprintln(w, "PID\tTTY\tTIME\tCMD")
-	for _, proc := range procs {
-		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", proc.PID, proc.Tty, proc.Time, proc.Cmd)
+	fmt.Fprintln(w, strings.Join(procs.Titles, "\t"))
+	for _, proc := range procs.Processes {
+		fmt.Fprintln(w, strings.Join(proc, "\t"))
 	}
 	}
 	w.Flush()
 	w.Flush()
 	return nil
 	return nil

+ 15 - 16
server.go

@@ -249,35 +249,34 @@ func (srv *Server) ImageHistory(name string) ([]APIHistory, error) {
 
 
 }
 }
 
 
-func (srv *Server) ContainerTop(name string) ([]APITop, error) {
+func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
 	if container := srv.runtime.Get(name); container != nil {
 	if container := srv.runtime.Get(name); container != nil {
-		output, err := exec.Command("lxc-ps", "--name", container.ID).CombinedOutput()
+		output, err := exec.Command("lxc-ps", "--name", container.ID, "--", ps_args).CombinedOutput()
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf("Error trying to use lxc-ps: %s (%s)", err, output)
 			return nil, fmt.Errorf("Error trying to use lxc-ps: %s (%s)", err, output)
 		}
 		}
-		var procs []APITop
+		procs := APITop{}
 		for i, line := range strings.Split(string(output), "\n") {
 		for i, line := range strings.Split(string(output), "\n") {
-			if i == 0 || len(line) == 0 {
+			if len(line) == 0 {
 				continue
 				continue
 			}
 			}
-			proc := APITop{}
+			words := []string{}
 			scanner := bufio.NewScanner(strings.NewReader(line))
 			scanner := bufio.NewScanner(strings.NewReader(line))
 			scanner.Split(bufio.ScanWords)
 			scanner.Split(bufio.ScanWords)
 			if !scanner.Scan() {
 			if !scanner.Scan() {
 				return nil, fmt.Errorf("Error trying to use lxc-ps")
 				return nil, fmt.Errorf("Error trying to use lxc-ps")
 			}
 			}
 			// no scanner.Text because we skip container id
 			// no scanner.Text because we skip container id
-			scanner.Scan()
-			proc.PID = scanner.Text()
-			scanner.Scan()
-			proc.Tty = scanner.Text()
-			scanner.Scan()
-			proc.Time = scanner.Text()
-			scanner.Scan()
-			proc.Cmd = scanner.Text()
-			procs = append(procs, proc)
-		}
-		return procs, nil
+			for scanner.Scan() {
+				words = append(words, scanner.Text())
+			}
+			if i == 0 {
+				procs.Titles = words
+			} else {
+				procs.Processes = append(procs.Processes, words)
+			}
+		}
+		return &procs, nil
 
 
 	}
 	}
 	return nil, fmt.Errorf("No such container: %s", name)
 	return nil, fmt.Errorf("No such container: %s", name)