Merge pull request #1238 from dotcloud/1237-improve_docker_top-feature
*Client: add ps args to docker top
This commit is contained in:
commit
dd2f0d89bf
7 changed files with 1164 additions and 40 deletions
11
api.go
11
api.go
|
@ -17,7 +17,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
const APIVERSION = 1.3
|
||||
const APIVERSION = 1.4
|
||||
const DEFAULTHTTPHOST string = "127.0.0.1"
|
||||
const DEFAULTHTTPPORT int = 4243
|
||||
|
||||
|
@ -271,11 +271,18 @@ func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r
|
|||
}
|
||||
|
||||
func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if version < 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
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -30,10 +30,8 @@ type APIInfo struct {
|
|||
}
|
||||
|
||||
type APITop struct {
|
||||
PID string
|
||||
Tty string
|
||||
Time string
|
||||
Cmd string
|
||||
Titles []string
|
||||
Processes [][]string
|
||||
}
|
||||
|
||||
type APIRmi struct {
|
||||
|
|
27
api_test.go
27
api_test.go
|
@ -482,24 +482,33 @@ func TestGetContainersTop(t *testing.T) {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
procs := []APITop{}
|
||||
if err := getContainersTop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
procs := APITop{}
|
||||
if err := json.Unmarshal(r.Body.Bytes(), &procs); err != nil {
|
||||
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.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[0].Cmd != "sh" && procs[0].Cmd != "busybox" {
|
||||
t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[0].Cmd)
|
||||
if len(procs.Processes) != 2 {
|
||||
t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes))
|
||||
}
|
||||
|
||||
if procs[1].Cmd != "sh" && procs[1].Cmd != "busybox" {
|
||||
t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[1].Cmd)
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
commands.go
17
commands.go
|
@ -604,23 +604,28 @@ func (cli *DockerCli) CmdTop(args ...string) error {
|
|||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
}
|
||||
if cmd.NArg() != 1 {
|
||||
if cmd.NArg() == 0 {
|
||||
cmd.Usage()
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
var procs []APITop
|
||||
procs := APITop{}
|
||||
err = json.Unmarshal(body, &procs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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()
|
||||
return nil
|
||||
|
|
|
@ -26,15 +26,15 @@ Docker Remote API
|
|||
2. Versions
|
||||
===========
|
||||
|
||||
The current verson of the API is 1.3
|
||||
The current verson of the API is 1.4
|
||||
|
||||
Calling /images/<name>/insert is the same as calling
|
||||
/v1.3/images/<name>/insert
|
||||
/v1.4/images/<name>/insert
|
||||
|
||||
You can still call an old version of the api using
|
||||
/v1.0/images/<name>/insert
|
||||
|
||||
:doc:`docker_remote_api_v1.3`
|
||||
:doc:`docker_remote_api_v1.4`
|
||||
*****************************
|
||||
|
||||
What's new
|
||||
|
@ -42,7 +42,19 @@ What's new
|
|||
|
||||
.. http:get:: /containers/(id)/top
|
||||
|
||||
**New!** List the processes running inside a container.
|
||||
**New!** You can now use ps args with docker top, like `docker top <container_id> aux`
|
||||
|
||||
:doc:`docker_remote_api_v1.3`
|
||||
*****************************
|
||||
|
||||
docker v0.5.0 51f6c4a_
|
||||
|
||||
What's new
|
||||
----------
|
||||
|
||||
.. http:get:: /containers/(id)/top
|
||||
|
||||
List the processes running inside a container.
|
||||
|
||||
.. http:get:: /events:
|
||||
|
||||
|
@ -138,6 +150,7 @@ Initial version
|
|||
.. _a8ae398: https://github.com/dotcloud/docker/commit/a8ae398bf52e97148ee7bd0d5868de2e15bd297f
|
||||
.. _8d73740: https://github.com/dotcloud/docker/commit/8d73740343778651c09160cde9661f5f387b36f4
|
||||
.. _2e7649b: https://github.com/dotcloud/docker/commit/2e7649beda7c820793bd46766cbc2cfeace7b168
|
||||
.. _51f6c4a: https://github.com/dotcloud/docker/commit/51f6c4a7372450d164c61e0054daf0223ddbd909
|
||||
|
||||
==================================
|
||||
Docker Remote API Client Libraries
|
||||
|
|
1093
docs/sources/api/docker_remote_api_v1.4.rst
Normal file
1093
docs/sources/api/docker_remote_api_v1.4.rst
Normal file
File diff suppressed because it is too large
Load diff
29
server.go
29
server.go
|
@ -309,35 +309,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 {
|
||||
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 {
|
||||
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") {
|
||||
if i == 0 || len(line) == 0 {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
proc := APITop{}
|
||||
words := []string{}
|
||||
scanner := bufio.NewScanner(strings.NewReader(line))
|
||||
scanner.Split(bufio.ScanWords)
|
||||
if !scanner.Scan() {
|
||||
return nil, fmt.Errorf("Error trying to use lxc-ps")
|
||||
}
|
||||
// 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)
|
||||
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 &procs, nil
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("No such container: %s", name)
|
||||
|
|
Loading…
Add table
Reference in a new issue