mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
add size to inspect
Signed-off-by: Zhang Kun <zkazure@gmail.com>
This commit is contained in:
parent
bf80adeee4
commit
b4d6b23838
13 changed files with 108 additions and 8 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
|
||||||
cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true)
|
cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true)
|
||||||
tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
|
tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
|
||||||
inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
|
inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
|
||||||
|
size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container")
|
||||||
cmd.Require(flag.Min, 1)
|
cmd.Require(flag.Min, 1)
|
||||||
|
|
||||||
cmd.ParseFlags(args, true)
|
cmd.ParseFlags(args, true)
|
||||||
|
@ -51,10 +53,15 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
|
||||||
status := 0
|
status := 0
|
||||||
isImage := false
|
isImage := false
|
||||||
|
|
||||||
|
v := url.Values{}
|
||||||
|
if *size {
|
||||||
|
v.Set("size", "1")
|
||||||
|
}
|
||||||
|
|
||||||
for _, name := range cmd.Args() {
|
for _, name := range cmd.Args() {
|
||||||
|
|
||||||
if *inspectType == "" || *inspectType == "container" {
|
if *inspectType == "" || *inspectType == "container" {
|
||||||
obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
|
obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json?"+v.Encode(), nil, nil))
|
||||||
if err != nil && *inspectType == "container" {
|
if err != nil && *inspectType == "container" {
|
||||||
if strings.Contains(err.Error(), "No such") {
|
if strings.Contains(err.Error(), "No such") {
|
||||||
fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)
|
fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
// getContainersByName inspects containers configuration and serializes it as json.
|
// getContainersByName inspects containers configuration and serializes it as json.
|
||||||
func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
displaySize := httputils.BoolValue(r, "size")
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
|
@ -25,7 +26,7 @@ func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter,
|
||||||
case version.Equal("1.20"):
|
case version.Equal("1.20"):
|
||||||
json, err = s.daemon.ContainerInspect120(vars["name"])
|
json, err = s.daemon.ContainerInspect120(vars["name"])
|
||||||
default:
|
default:
|
||||||
json, err = s.daemon.ContainerInspect(vars["name"])
|
json, err = s.daemon.ContainerInspect(vars["name"], displaySize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -269,6 +269,8 @@ type ContainerJSONBase struct {
|
||||||
ExecIDs []string
|
ExecIDs []string
|
||||||
HostConfig *runconfig.HostConfig
|
HostConfig *runconfig.HostConfig
|
||||||
GraphDriver GraphDriverData
|
GraphDriver GraphDriverData
|
||||||
|
SizeRw *int64 `json:",omitempty"`
|
||||||
|
SizeRootFs *int64 `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerJSON is newly used struct along with MountPoint
|
// 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
|
||||||
complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container or image'
|
complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container or image'
|
||||||
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s f -l format -d 'Format the output using the given go template.'
|
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s f -l format -d 'Format the output using the given go template.'
|
||||||
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -l help -d 'Print usage'
|
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -l help -d 'Print usage'
|
||||||
|
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.'
|
||||||
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_images)' -d "Image"
|
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_images)' -d "Image"
|
||||||
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_containers all)' -d "Container"
|
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_containers all)' -d "Container"
|
||||||
|
|
||||||
|
|
|
@ -548,6 +548,7 @@ __docker_subcommand() {
|
||||||
_arguments \
|
_arguments \
|
||||||
$opts_help \
|
$opts_help \
|
||||||
"($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
|
"($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
|
||||||
|
"($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \
|
||||||
"($help)--type=-[Return JSON for specified type]:type:(image container)" \
|
"($help)--type=-[Return JSON for specified type]:type:(image container)" \
|
||||||
"($help -)*: :->values" && ret=0
|
"($help -)*: :->values" && ret=0
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// ContainerInspect returns low-level information about a
|
// ContainerInspect returns low-level information about a
|
||||||
// container. Returns an error if the container cannot be found, or if
|
// container. Returns an error if the container cannot be found, or if
|
||||||
// there is an error getting the data.
|
// there is an error getting the data.
|
||||||
func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error) {
|
func (daemon *Daemon) ContainerInspect(name string, size bool) (*types.ContainerJSON, error) {
|
||||||
container, err := daemon.Get(name)
|
container, err := daemon.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -20,7 +20,7 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
|
||||||
container.Lock()
|
container.Lock()
|
||||||
defer container.Unlock()
|
defer container.Unlock()
|
||||||
|
|
||||||
base, err := daemon.getInspectData(container)
|
base, err := daemon.getInspectData(container, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er
|
||||||
container.Lock()
|
container.Lock()
|
||||||
defer container.Unlock()
|
defer container.Unlock()
|
||||||
|
|
||||||
base, err := daemon.getInspectData(container)
|
base, err := daemon.getInspectData(container, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er
|
||||||
return &v1p20.ContainerJSON{base, mountPoints, config}, nil
|
return &v1p20.ContainerJSON{base, mountPoints, config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
|
func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.ContainerJSONBase, error) {
|
||||||
// make a copy to play with
|
// make a copy to play with
|
||||||
hostConfig := *container.hostConfig
|
hostConfig := *container.hostConfig
|
||||||
|
|
||||||
|
@ -106,6 +106,16 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
|
||||||
HostConfig: &hostConfig,
|
HostConfig: &hostConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
sizeRw int64
|
||||||
|
sizeRootFs int64
|
||||||
|
)
|
||||||
|
if size {
|
||||||
|
sizeRw, sizeRootFs = container.getSize()
|
||||||
|
contJSONBase.SizeRw = &sizeRw
|
||||||
|
contJSONBase.SizeRootFs = &sizeRootFs
|
||||||
|
}
|
||||||
|
|
||||||
// Now set any platform-specific fields
|
// Now set any platform-specific fields
|
||||||
contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
|
contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*v1p19.ContainerJSON,
|
||||||
container.Lock()
|
container.Lock()
|
||||||
defer container.Unlock()
|
defer container.Unlock()
|
||||||
|
|
||||||
base, err := daemon.getInspectData(container)
|
base, err := daemon.getInspectData(container, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,5 @@ func addMountPoints(container *Container) []types.MountPoint {
|
||||||
|
|
||||||
// ContainerInspectPre120 get containers for pre 1.20 APIs.
|
// ContainerInspectPre120 get containers for pre 1.20 APIs.
|
||||||
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
|
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
|
||||||
return daemon.ContainerInspect(name)
|
return daemon.ContainerInspect(name, false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ list of DNS options to be used in the container.
|
||||||
* `GET /info` now lists engine version information.
|
* `GET /info` now lists engine version information.
|
||||||
* `GET /containers/json` will return `ImageID` of the image used by container.
|
* `GET /containers/json` will return `ImageID` of the image used by container.
|
||||||
* `POST /exec/(name)/start` will now return an HTTP 409 when the container is either stopped or paused.
|
* `POST /exec/(name)/start` will now return an HTTP 409 when the container is either stopped or paused.
|
||||||
|
* `GET /containers/(name)/json` now accepts a `size` parameter. Setting this parameter to '1' returns container size information in the `SizeRw` and `SizeRootFs` fields.
|
||||||
|
|
||||||
### v1.20 API changes
|
### v1.20 API changes
|
||||||
|
|
||||||
|
|
|
@ -466,6 +466,26 @@ Return low-level information on the container `id`
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
**Example request, with size information**:
|
||||||
|
|
||||||
|
GET /containers/4fa6e0f0c678/json?size=1 HTTP/1.1
|
||||||
|
|
||||||
|
**Example response, with size information**:
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
....
|
||||||
|
"SizeRw": 0,
|
||||||
|
"SizeRootFs": 972,
|
||||||
|
....
|
||||||
|
}
|
||||||
|
|
||||||
|
Query Parameters:
|
||||||
|
|
||||||
|
- **size** – 1/True/true or 0/False/false, return container size information. Default is `false`.
|
||||||
|
|
||||||
Status Codes:
|
Status Codes:
|
||||||
|
|
||||||
- **200** – no error
|
- **200** – no error
|
||||||
|
|
|
@ -18,6 +18,7 @@ parent = "smn_cli"
|
||||||
--help=false Print usage
|
--help=false Print usage
|
||||||
--type=container|image Return JSON for specified type, permissible
|
--type=container|image Return JSON for specified type, permissible
|
||||||
values are "image" or "container"
|
values are "image" or "container"
|
||||||
|
-s, --size=false Display total file sizes if the type is container
|
||||||
|
|
||||||
By default, this will render all results in a JSON array. If a format is
|
By default, this will render all results in a JSON array. If a format is
|
||||||
specified, the given template will be executed for each result.
|
specified, the given template will be executed for each result.
|
||||||
|
|
|
@ -345,3 +345,43 @@ func (s *DockerSuite) TestInspectLogConfigNoType(c *check.C) {
|
||||||
c.Assert(logConfig.Type, check.Equals, "json-file")
|
c.Assert(logConfig.Type, check.Equals, "json-file")
|
||||||
c.Assert(logConfig.Config["max-file"], check.Equals, "42", check.Commentf("%v", logConfig))
|
c.Assert(logConfig.Config["max-file"], check.Equals, "42", check.Commentf("%v", logConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestInspectNoSizeFlagContainer(c *check.C) {
|
||||||
|
|
||||||
|
//Both the container and image are named busybox. docker inspect will fetch container
|
||||||
|
//JSON SizeRw and SizeRootFs field. If there is no flag --size/-s, there are no size fields.
|
||||||
|
|
||||||
|
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
|
||||||
|
|
||||||
|
formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
|
||||||
|
out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
|
||||||
|
c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Exepcted not to display size info: %s", out))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestInspectSizeFlagContainer(c *check.C) {
|
||||||
|
|
||||||
|
//Both the container and image are named busybox. docker inspect will fetch container
|
||||||
|
//JSON SizeRw and SizeRootFs field. If there is a flag --size/-s, the fields are not <no value>.
|
||||||
|
|
||||||
|
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
|
||||||
|
|
||||||
|
formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
|
||||||
|
out, _ := dockerCmd(c, "inspect", "-s", "--type=container", formatStr, "busybox")
|
||||||
|
sz := strings.Split(out, ",")
|
||||||
|
|
||||||
|
c.Assert(strings.TrimSpace(sz[0]), check.Not(check.Equals), "<nil>")
|
||||||
|
c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "<nil>")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestInspectSizeFlagImage(c *check.C) {
|
||||||
|
|
||||||
|
//Both the container and image are named busybox. docker inspect will fetch image
|
||||||
|
//JSON SizeRw and SizeRootFs field. There are no these fields since they are only in containers.
|
||||||
|
|
||||||
|
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
|
||||||
|
|
||||||
|
formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
|
||||||
|
out, _ := dockerCmd(c, "inspect", "-s", "--type=image", formatStr, "busybox")
|
||||||
|
|
||||||
|
c.Assert(strings.TrimSpace(out), check.Equals, "<no value>,<no value>", check.Commentf("Fields SizeRw and SizeRootFs are not exepcted to exist"))
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ docker-inspect - Return low-level information on a container or image
|
||||||
**docker inspect**
|
**docker inspect**
|
||||||
[**--help**]
|
[**--help**]
|
||||||
[**-f**|**--format**[=*FORMAT*]]
|
[**-f**|**--format**[=*FORMAT*]]
|
||||||
|
[**-s**|**--size**[=*false*]]
|
||||||
[**--type**=*container*|*image*]
|
[**--type**=*container*|*image*]
|
||||||
CONTAINER|IMAGE [CONTAINER|IMAGE...]
|
CONTAINER|IMAGE [CONTAINER|IMAGE...]
|
||||||
|
|
||||||
|
@ -25,6 +26,9 @@ each result.
|
||||||
**-f**, **--format**=""
|
**-f**, **--format**=""
|
||||||
Format the output using the given Go template.
|
Format the output using the given Go template.
|
||||||
|
|
||||||
|
**-s**, **--size**=false
|
||||||
|
Display total file sizes if the type is container.
|
||||||
|
|
||||||
**--type**=*container*|*image*
|
**--type**=*container*|*image*
|
||||||
Return JSON for specified type, permissible values are "image" or "container"
|
Return JSON for specified type, permissible values are "image" or "container"
|
||||||
|
|
||||||
|
@ -205,6 +209,18 @@ output:
|
||||||
You can get more information about how to write a Go template from:
|
You can get more information about how to write a Go template from:
|
||||||
https://golang.org/pkg/text/template/.
|
https://golang.org/pkg/text/template/.
|
||||||
|
|
||||||
|
## Getting size information on an container
|
||||||
|
|
||||||
|
$ docker inspect -s d2cc496561d6
|
||||||
|
[
|
||||||
|
{
|
||||||
|
....
|
||||||
|
"SizeRw": 0,
|
||||||
|
"SizeRootFs": 972,
|
||||||
|
....
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
## Getting information on an image
|
## Getting information on an image
|
||||||
|
|
||||||
Use an image's ID or name (e.g., repository/name[:tag]) to get information
|
Use an image's ID or name (e.g., repository/name[:tag]) to get information
|
||||||
|
|
Loading…
Add table
Reference in a new issue