diff --git a/api/client/top.go b/api/client/top.go index 9de04cac68..4975f47597 100644 --- a/api/client/top.go +++ b/api/client/top.go @@ -1,12 +1,13 @@ package client import ( + "encoding/json" "fmt" "net/url" "strings" "text/tabwriter" - "github.com/docker/docker/engine" + "github.com/docker/docker/api/types" flag "github.com/docker/docker/pkg/mflag" ) @@ -28,17 +29,17 @@ func (cli *DockerCli) CmdTop(args ...string) error { if err != nil { return err } - var procs engine.Env - if err := procs.Decode(stream); err != nil { + + procList := types.ContainerProcessList{} + err = json.NewDecoder(stream).Decode(&procList) + if err != nil { return err } + w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - fmt.Fprintln(w, strings.Join(procs.GetList("Titles"), "\t")) - processes := [][]string{} - if err := procs.GetJson("Processes", &processes); err != nil { - return err - } - for _, proc := range processes { + fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) + + for _, proc := range procList.Processes { fmt.Fprintln(w, strings.Join(proc, "\t")) } w.Flush() diff --git a/api/server/server.go b/api/server/server.go index 912af638ce..7b38ea30cc 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -471,16 +471,21 @@ func getContainersTop(eng *engine.Engine, version version.Version, w http.Respon if version.LessThan("1.4") { return fmt.Errorf("top was improved a lot since 1.3, Please upgrade your docker client.") } + if vars == nil { return fmt.Errorf("Missing parameter") } + if err := parseForm(r); err != nil { return err } - job := eng.Job("top", vars["name"], r.Form.Get("ps_args")) - streamJSON(job, w, false) - return job.Run() + procList, err := getDaemon(eng).ContainerTop(vars["name"], r.Form.Get("ps_args")) + if err != nil { + return err + } + + return writeJSON(w, http.StatusOK, procList) } func getContainersJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { diff --git a/api/types/types.go b/api/types/types.go index 77b211705d..48c9265a50 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -103,3 +103,9 @@ type Container struct { type CopyConfig struct { Resource string } + +// GET "/containers/{name:.*}/top" +type ContainerProcessList struct { + Processes [][]string + Titles []string +} diff --git a/daemon/daemon.go b/daemon/daemon.go index 06e9bb440a..ea49a8b87c 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -128,7 +128,6 @@ func (daemon *Daemon) Install(eng *engine.Engine) error { "restart": daemon.ContainerRestart, "start": daemon.ContainerStart, "stop": daemon.ContainerStop, - "top": daemon.ContainerTop, "wait": daemon.ContainerWait, "execCreate": daemon.ContainerExecCreate, "execStart": daemon.ContainerExecStart, diff --git a/daemon/top.go b/daemon/top.go index 1e8c39987c..14b2523705 100644 --- a/daemon/top.go +++ b/daemon/top.go @@ -6,54 +6,48 @@ import ( "strconv" "strings" - "github.com/docker/docker/engine" + "github.com/docker/docker/api/types" ) -func (daemon *Daemon) ContainerTop(job *engine.Job) error { - if len(job.Args) != 1 && len(job.Args) != 2 { - return fmt.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name) - } - var ( - name = job.Args[0] +func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) { + if psArgs == "" { psArgs = "-ef" - ) - - if len(job.Args) == 2 && job.Args[1] != "" { - psArgs = job.Args[1] } container, err := daemon.Get(name) if err != nil { - return err + return nil, err } + if !container.IsRunning() { - return fmt.Errorf("Container %s is not running", name) + return nil, fmt.Errorf("Container %s is not running", name) } + pids, err := daemon.ExecutionDriver().GetPidsForContainer(container.ID) if err != nil { - return err + return nil, err } + output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output() if err != nil { - return fmt.Errorf("Error running ps: %s", err) + return nil, fmt.Errorf("Error running ps: %s", err) } + procList := &types.ContainerProcessList{} + lines := strings.Split(string(output), "\n") - header := strings.Fields(lines[0]) - out := &engine.Env{} - out.SetList("Titles", header) + procList.Titles = strings.Fields(lines[0]) pidIndex := -1 - for i, name := range header { + for i, name := range procList.Titles { if name == "PID" { pidIndex = i } } if pidIndex == -1 { - return fmt.Errorf("Couldn't find PID field in ps output") + return nil, fmt.Errorf("Couldn't find PID field in ps output") } - processes := [][]string{} for _, line := range lines[1:] { if len(line) == 0 { continue @@ -61,20 +55,18 @@ func (daemon *Daemon) ContainerTop(job *engine.Job) error { fields := strings.Fields(line) p, err := strconv.Atoi(fields[pidIndex]) if err != nil { - return fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) + return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) } for _, pid := range pids { if pid == p { // Make sure number of fields equals number of header titles // merging "overhanging" fields - process := fields[:len(header)-1] - process = append(process, strings.Join(fields[len(header)-1:], " ")) - processes = append(processes, process) + process := fields[:len(procList.Titles)-1] + process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) + procList.Processes = append(procList.Processes, process) } } } - out.SetJson("Processes", processes) - out.WriteTo(job.Stdout) - return nil + return procList, nil }