Browse code

Merge pull request #15796 from azurezk/add-size-to-inspect

add container size info to inspect

Vincent Demeester authored on 2015/10/14 06:16:10
Showing 13 changed files
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"encoding/json"
6 6
 	"fmt"
7 7
 	"io"
8
+	"net/url"
8 9
 	"strings"
9 10
 	"text/template"
10 11
 
... ...
@@ -27,6 +28,7 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
27 27
 	cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true)
28 28
 	tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
29 29
 	inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
30
+	size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container")
30 31
 	cmd.Require(flag.Min, 1)
31 32
 
32 33
 	cmd.ParseFlags(args, true)
... ...
@@ -51,10 +53,15 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
51 51
 	status := 0
52 52
 	isImage := false
53 53
 
54
+	v := url.Values{}
55
+	if *size {
56
+		v.Set("size", "1")
57
+	}
58
+
54 59
 	for _, name := range cmd.Args() {
55 60
 
56 61
 		if *inspectType == "" || *inspectType == "container" {
57
-			obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
62
+			obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json?"+v.Encode(), nil, nil))
58 63
 			if err != nil && *inspectType == "container" {
59 64
 				if strings.Contains(err.Error(), "No such") {
60 65
 					fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)
... ...
@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 // getContainersByName inspects containers configuration and serializes it as json.
12 12
 func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
13
+	displaySize := httputils.BoolValue(r, "size")
13 14
 	if vars == nil {
14 15
 		return fmt.Errorf("Missing parameter")
15 16
 	}
... ...
@@ -25,7 +26,7 @@ func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter,
25 25
 	case version.Equal("1.20"):
26 26
 		json, err = s.daemon.ContainerInspect120(vars["name"])
27 27
 	default:
28
-		json, err = s.daemon.ContainerInspect(vars["name"])
28
+		json, err = s.daemon.ContainerInspect(vars["name"], displaySize)
29 29
 	}
30 30
 
31 31
 	if err != nil {
... ...
@@ -269,6 +269,8 @@ type ContainerJSONBase struct {
269 269
 	ExecIDs         []string
270 270
 	HostConfig      *runconfig.HostConfig
271 271
 	GraphDriver     GraphDriverData
272
+	SizeRw          *int64 `json:",omitempty"`
273
+	SizeRootFs      *int64 `json:",omitempty"`
272 274
 }
273 275
 
274 276
 // ContainerJSON is newly used struct along with MountPoint
... ...
@@ -207,6 +207,7 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a info -d 'Display syste
207 207
 complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container or image'
208 208
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s f -l format -d 'Format the output using the given go template.'
209 209
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -l help -d 'Print usage'
210
+complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s s -l size -d 'Display total file sizes if the type is container.'
210 211
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_images)' -d "Image"
211 212
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_containers all)' -d "Container"
212 213
 
... ...
@@ -650,6 +650,7 @@ __docker_subcommand() {
650 650
             _arguments \
651 651
                 $opts_help \
652 652
                 "($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
653
+                "($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \
653 654
                 "($help)--type=-[Return JSON for specified type]:type:(image container)" \
654 655
                 "($help -)*: :->values" && ret=0
655 656
 
... ...
@@ -11,7 +11,7 @@ import (
11 11
 // ContainerInspect returns low-level information about a
12 12
 // container. Returns an error if the container cannot be found, or if
13 13
 // there is an error getting the data.
14
-func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error) {
14
+func (daemon *Daemon) ContainerInspect(name string, size bool) (*types.ContainerJSON, error) {
15 15
 	container, err := daemon.Get(name)
16 16
 	if err != nil {
17 17
 		return nil, err
... ...
@@ -20,7 +20,7 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
20 20
 	container.Lock()
21 21
 	defer container.Unlock()
22 22
 
23
-	base, err := daemon.getInspectData(container)
23
+	base, err := daemon.getInspectData(container, size)
24 24
 	if err != nil {
25 25
 		return nil, err
26 26
 	}
... ...
@@ -40,7 +40,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er
40 40
 	container.Lock()
41 41
 	defer container.Unlock()
42 42
 
43
-	base, err := daemon.getInspectData(container)
43
+	base, err := daemon.getInspectData(container, false)
44 44
 	if err != nil {
45 45
 		return nil, err
46 46
 	}
... ...
@@ -54,7 +54,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er
54 54
 	return &v1p20.ContainerJSON{base, mountPoints, config}, nil
55 55
 }
56 56
 
57
-func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
57
+func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.ContainerJSONBase, error) {
58 58
 	// make a copy to play with
59 59
 	hostConfig := *container.hostConfig
60 60
 
... ...
@@ -106,6 +106,16 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
106 106
 		HostConfig:      &hostConfig,
107 107
 	}
108 108
 
109
+	var (
110
+		sizeRw     int64
111
+		sizeRootFs int64
112
+	)
113
+	if size {
114
+		sizeRw, sizeRootFs = container.getSize()
115
+		contJSONBase.SizeRw = &sizeRw
116
+		contJSONBase.SizeRootFs = &sizeRootFs
117
+	}
118
+
109 119
 	// Now set any platform-specific fields
110 120
 	contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
111 121
 
... ...
@@ -27,7 +27,7 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*v1p19.ContainerJSON,
27 27
 	container.Lock()
28 28
 	defer container.Unlock()
29 29
 
30
-	base, err := daemon.getInspectData(container)
30
+	base, err := daemon.getInspectData(container, false)
31 31
 	if err != nil {
32 32
 		return nil, err
33 33
 	}
... ...
@@ -13,5 +13,5 @@ func addMountPoints(container *Container) []types.MountPoint {
13 13
 
14 14
 // ContainerInspectPre120 get containers for pre 1.20 APIs.
15 15
 func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
16
-	return daemon.ContainerInspect(name)
16
+	return daemon.ContainerInspect(name, false)
17 17
 }
... ...
@@ -109,6 +109,7 @@ list of DNS options to be used in the container.
109 109
 * `GET /info` now lists engine version information.
110 110
 * `GET /containers/json` will return `ImageID` of the image used by container.
111 111
 * `POST /exec/(name)/start` will now return an HTTP 409 when the container is either stopped or paused.
112
+* `GET /containers/(name)/json` now accepts a `size` parameter. Setting this parameter to '1' returns container size information in the `SizeRw` and `SizeRootFs` fields.
112 113
 
113 114
 ### v1.20 API changes
114 115
 
... ...
@@ -467,6 +467,26 @@ Return low-level information on the container `id`
467 467
 		]
468 468
 	}
469 469
 
470
+**Example request, with size information**:
471
+
472
+    GET /containers/4fa6e0f0c678/json?size=1 HTTP/1.1
473
+
474
+**Example response, with size information**:
475
+
476
+    HTTP/1.1 200 OK
477
+    Content-Type: application/json
478
+
479
+    {
480
+    ....
481
+    "SizeRw": 0,
482
+    "SizeRootFs": 972,
483
+    ....
484
+    }
485
+
486
+Query Parameters:
487
+
488
+-   **size** – 1/True/true or 0/False/false, return container size information. Default is `false`.
489
+
470 490
 Status Codes:
471 491
 
472 492
 -   **200** – no error
... ...
@@ -18,6 +18,7 @@ parent = "smn_cli"
18 18
       --help=false            Print usage
19 19
       --type=container|image  Return JSON for specified type, permissible
20 20
                               values are "image" or "container"
21
+      -s, --size=false        Display total file sizes if the type is container
21 22
 
22 23
 By default, this will render all results in a JSON array. If a format is
23 24
 specified, the given template will be executed for each result.
... ...
@@ -345,3 +345,43 @@ func (s *DockerSuite) TestInspectLogConfigNoType(c *check.C) {
345 345
 	c.Assert(logConfig.Type, check.Equals, "json-file")
346 346
 	c.Assert(logConfig.Config["max-file"], check.Equals, "42", check.Commentf("%v", logConfig))
347 347
 }
348
+
349
+func (s *DockerSuite) TestInspectNoSizeFlagContainer(c *check.C) {
350
+
351
+	//Both the container and image are named busybox. docker inspect will fetch container
352
+	//JSON SizeRw and SizeRootFs field. If there is no flag --size/-s, there are no size fields.
353
+
354
+	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
355
+
356
+	formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
357
+	out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
358
+	c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Exepcted not to display size info: %s", out))
359
+}
360
+
361
+func (s *DockerSuite) TestInspectSizeFlagContainer(c *check.C) {
362
+
363
+	//Both the container and image are named busybox. docker inspect will fetch container
364
+	//JSON SizeRw and SizeRootFs field. If there is a flag --size/-s, the fields are not <no value>.
365
+
366
+	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
367
+
368
+	formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
369
+	out, _ := dockerCmd(c, "inspect", "-s", "--type=container", formatStr, "busybox")
370
+	sz := strings.Split(out, ",")
371
+
372
+	c.Assert(strings.TrimSpace(sz[0]), check.Not(check.Equals), "<nil>")
373
+	c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "<nil>")
374
+}
375
+
376
+func (s *DockerSuite) TestInspectSizeFlagImage(c *check.C) {
377
+
378
+	//Both the container and image are named busybox. docker inspect will fetch image
379
+	//JSON SizeRw and SizeRootFs field. There are no these fields since they are only in containers.
380
+
381
+	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
382
+
383
+	formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
384
+	out, _ := dockerCmd(c, "inspect", "-s", "--type=image", formatStr, "busybox")
385
+
386
+	c.Assert(strings.TrimSpace(out), check.Equals, "<no value>,<no value>", check.Commentf("Fields SizeRw and SizeRootFs are not exepcted to exist"))
387
+}
... ...
@@ -8,6 +8,7 @@ docker-inspect - Return low-level information on a container or image
8 8
 **docker inspect**
9 9
 [**--help**]
10 10
 [**-f**|**--format**[=*FORMAT*]]
11
+[**-s**|**--size**[=*false*]]
11 12
 [**--type**=*container*|*image*]
12 13
 CONTAINER|IMAGE [CONTAINER|IMAGE...]
13 14
 
... ...
@@ -25,6 +26,9 @@ each result.
25 25
 **-f**, **--format**=""
26 26
     Format the output using the given Go template.
27 27
 
28
+**-s**, **--size**=false
29
+    Display total file sizes if the type is container.
30
+
28 31
 **--type**=*container*|*image*
29 32
     Return JSON for specified type, permissible values are "image" or "container"
30 33
 
... ...
@@ -205,6 +209,18 @@ output:
205 205
 You can get more information about how to write a Go template from:
206 206
 https://golang.org/pkg/text/template/.
207 207
 
208
+## Getting size information on an container
209
+
210
+    $ docker inspect -s d2cc496561d6
211
+    [
212
+    {
213
+    ....
214
+    "SizeRw": 0,
215
+    "SizeRootFs": 972,
216
+    ....
217
+    }
218
+    ]
219
+
208 220
 ## Getting information on an image
209 221
 
210 222
 Use an image's ID or name (e.g., repository/name[:tag]) to get information