diff --git a/api.go b/api.go index 194cf6058b..3155bf5513 100644 --- a/api.go +++ b/api.go @@ -69,15 +69,15 @@ func writeJSON(w http.ResponseWriter, b []byte) { w.Write(b) } -// FIXME: Use stvconv.ParseBool() instead? func getBoolParam(value string) (bool, error) { - if value == "1" || strings.ToLower(value) == "true" { - return true, nil - } - if value == "" || value == "0" || strings.ToLower(value) == "false" { + if value == "" { return false, nil } - return false, fmt.Errorf("Bad parameter") + ret, err := strconv.ParseBool(value) + if err != nil { + return false, fmt.Errorf("Bad parameter") + } + return ret, nil } func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { @@ -258,6 +258,10 @@ func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *h if err != nil { return err } + size, err := getBoolParam(r.Form.Get("size")) + if err != nil { + return err + } since := r.Form.Get("since") before := r.Form.Get("before") n, err := strconv.Atoi(r.Form.Get("limit")) @@ -265,7 +269,7 @@ func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *h n = -1 } - outs := srv.Containers(all, n, since, before) + outs := srv.Containers(all, size, n, since, before) b, err := json.Marshal(outs) if err != nil { return err diff --git a/api_test.go b/api_test.go index 40b31d4961..12ea5ee962 100644 --- a/api_test.go +++ b/api_test.go @@ -17,6 +17,30 @@ import ( "time" ) +func TestGetBoolParam(t *testing.T) { + if ret, err := getBoolParam("true"); err != nil || !ret { + t.Fatalf("true -> true, nil | got %b %s", ret, err) + } + if ret, err := getBoolParam("True"); err != nil || !ret { + t.Fatalf("True -> true, nil | got %b %s", ret, err) + } + if ret, err := getBoolParam("1"); err != nil || !ret { + t.Fatalf("1 -> true, nil | got %b %s", ret, err) + } + if ret, err := getBoolParam(""); err != nil || ret { + t.Fatalf("\"\" -> false, nil | got %b %s", ret, err) + } + if ret, err := getBoolParam("false"); err != nil || ret { + t.Fatalf("false -> false, nil | got %b %s", ret, err) + } + if ret, err := getBoolParam("0"); err != nil || ret { + t.Fatalf("0 -> false, nil | got %b %s", ret, err) + } + if ret, err := getBoolParam("faux"); err == nil || ret { + t.Fatalf("faux -> false, err | got %b %s", ret, err) + } +} + func TestPostAuth(t *testing.T) { runtime, err := newTestRuntime() if err != nil { diff --git a/commands.go b/commands.go index c6a5c3ba24..a8302202e0 100644 --- a/commands.go +++ b/commands.go @@ -878,6 +878,7 @@ func (cli *DockerCli) CmdImages(args ...string) error { func (cli *DockerCli) CmdPs(args ...string) error { cmd := Subcmd("ps", "[OPTIONS]", "List containers") quiet := cmd.Bool("q", false, "Only display numeric IDs") + size := cmd.Bool("s", false, "Display sizes") all := cmd.Bool("a", false, "Show all containers. Only running containers are shown by default.") noTrunc := cmd.Bool("notrunc", false, "Don't truncate output") nLatest := cmd.Bool("l", false, "Show only the latest created container, include non-running ones.") @@ -904,6 +905,9 @@ func (cli *DockerCli) CmdPs(args ...string) error { if *before != "" { v.Set("before", *before) } + if *size { + v.Set("size", "1") + } body, _, err := cli.call("GET", "/containers/json?"+v.Encode(), nil) if err != nil { @@ -917,7 +921,12 @@ func (cli *DockerCli) CmdPs(args ...string) error { } w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0) if !*quiet { - fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tSIZE") + fmt.Fprint(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS") + if *size { + fmt.Fprintln(w, "\tSIZE") + } else { + fmt.Fprint(w, "\n") + } } for _, out := range outs { @@ -927,10 +936,14 @@ func (cli *DockerCli) CmdPs(args ...string) error { } else { fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t", utils.TruncateID(out.ID), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) } - if out.SizeRootFs > 0 { - fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.SizeRw), utils.HumanSize(out.SizeRootFs)) + if *size { + if out.SizeRootFs > 0 { + fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.SizeRw), utils.HumanSize(out.SizeRootFs)) + } else { + fmt.Fprintf(w, "%s\n", utils.HumanSize(out.SizeRw)) + } } else { - fmt.Fprintf(w, "%s\n", utils.HumanSize(out.SizeRw)) + fmt.Fprint(w, "\n") } } else { if *noTrunc { diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index d081608029..02af1ccc92 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -30,6 +30,7 @@ What's new ---------- Builder (/build): + - Simplify the upload of the build context - Simply stream a tarball instead of multipart upload with 4 intermediary buffers - Simpler, less memory usage, less disk usage and faster @@ -37,10 +38,16 @@ Builder (/build): .. Note:: The /build improvements are not reverse-compatible. Pre 1.3 clients will break on /build. +List containers (/containers/json): + +- You can use size=1 to get the size of the containers + :doc:`docker_remote_api_v1.2` ***************************** +docker v0.4.2 2e7649b_ + What's new ---------- @@ -80,6 +87,9 @@ Uses json stream instead of HTML hijack, it looks like this: ... +:doc:`docker_remote_api_v1.0` +***************************** + docker v0.3.4 8d73740_ What's new @@ -90,6 +100,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 ================================== Docker Remote API Client Libraries diff --git a/docs/sources/api/docker_remote_api_v1.3.rst b/docs/sources/api/docker_remote_api_v1.3.rst index 2237b52398..a8e14ec461 100644 --- a/docs/sources/api/docker_remote_api_v1.3.rst +++ b/docs/sources/api/docker_remote_api_v1.3.rst @@ -32,7 +32,7 @@ List containers .. sourcecode:: http - GET /containers/json?all=1&before=8dfafdbc3a40 HTTP/1.1 + GET /containers/json?all=1&before=8dfafdbc3a40&size=1 HTTP/1.1 **Example response**: @@ -88,6 +88,7 @@ List containers :query limit: Show ``limit`` last created containers, include non-running ones. :query since: Show only containers created since Id, include non-running ones. :query before: Show only containers created before Id, include non-running ones. + :query size: 1/True/true or 0/False/false, Show the containers sizes :statuscode 200: no error :statuscode 400: bad parameter :statuscode 500: server error diff --git a/server.go b/server.go index ad4f092a7f..5fdfd00a49 100644 --- a/server.go +++ b/server.go @@ -254,7 +254,7 @@ func (srv *Server) ContainerChanges(name string) ([]Change, error) { return nil, fmt.Errorf("No such container: %s", name) } -func (srv *Server) Containers(all bool, n int, since, before string) []APIContainers { +func (srv *Server) Containers(all, size bool, n int, since, before string) []APIContainers { var foundBefore bool var displayed int retContainers := []APIContainers{} @@ -288,8 +288,9 @@ func (srv *Server) Containers(all bool, n int, since, before string) []APIContai c.Created = container.Created.Unix() c.Status = container.State.String() c.Ports = container.NetworkSettings.PortMappingHuman() - c.SizeRw, c.SizeRootFs = container.GetSize() - + if size { + c.SizeRw, c.SizeRootFs = container.GetSize() + } retContainers = append(retContainers, c) } return retContainers