1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Refactor docker inspect to work on all types

Signed-off-by: Arnaud Porterie (icecrime) <arnaud.porterie@docker.com>
This commit is contained in:
Arnaud Porterie (icecrime) 2016-06-15 21:41:54 -07:00
parent 15f3d060ac
commit 3db9f7afce
No known key found for this signature in database
GPG key ID: 3D78FAF1AF91D9E9
5 changed files with 98 additions and 63 deletions

View file

@ -36,68 +36,101 @@ func NewInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template") flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type, (e.g image, container or task)") flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type")
flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container") flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")
return cmd return cmd
} }
func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error { func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
ctx := context.Background() var elementSearcher inspect.GetRefFunc
client := dockerCli.Client()
var getRefFunc inspect.GetRefFunc
switch opts.inspectType { switch opts.inspectType {
case "container": case "", "container", "image", "node", "network", "service", "volume", "task":
getRefFunc = func(ref string) (interface{}, []byte, error) { elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
return client.ContainerInspectWithRaw(ctx, ref, opts.size)
}
case "image":
getRefFunc = func(ref string) (interface{}, []byte, error) {
return client.ImageInspectWithRaw(ctx, ref)
}
case "task":
if opts.size {
fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
}
getRefFunc = func(ref string) (interface{}, []byte, error) {
return client.TaskInspectWithRaw(ctx, ref)
}
case "":
getRefFunc = inspectAll(ctx, dockerCli, opts.size)
default: default:
return fmt.Errorf("%q is not a valid value for --type", opts.inspectType) return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
} }
return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, getRefFunc)
} }
func inspectAll(ctx context.Context, dockerCli *client.DockerCli, getSize bool) inspect.GetRefFunc { func inspectContainers(ctx context.Context, dockerCli *client.DockerCli, getSize bool) inspect.GetRefFunc {
client := dockerCli.Client()
return func(ref string) (interface{}, []byte, error) { return func(ref string) (interface{}, []byte, error) {
c, rawContainer, err := client.ContainerInspectWithRaw(ctx, ref, getSize) return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize)
if err == nil || !apiclient.IsErrNotFound(err) {
return c, rawContainer, err
}
// Search for image with that id if a container doesn't exist.
i, rawImage, err := client.ImageInspectWithRaw(ctx, ref)
if err == nil || !apiclient.IsErrNotFound(err) {
return i, rawImage, err
}
// Search for task with that id if an image doesn't exist.
t, rawTask, err := client.TaskInspectWithRaw(ctx, ref)
if err == nil || !(apiclient.IsErrNotFound(err) || isErrorNoSwarmMode(err)) {
if getSize {
fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
}
return t, rawTask, err
}
return nil, nil, fmt.Errorf("Error: No such container, image or task: %s", ref)
} }
} }
func isErrorNoSwarmMode(err error) bool { func inspectImages(ctx context.Context, dockerCli *client.DockerCli) inspect.GetRefFunc {
return strings.Contains(err.Error(), "This node is not a swarm manager") return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().ImageInspectWithRaw(ctx, ref)
}
}
func inspectNetwork(ctx context.Context, dockerCli *client.DockerCli) inspect.GetRefFunc {
return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().NetworkInspectWithRaw(ctx, ref)
}
}
func inspectNode(ctx context.Context, dockerCli *client.DockerCli) inspect.GetRefFunc {
return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().NodeInspectWithRaw(ctx, ref)
}
}
func inspectService(ctx context.Context, dockerCli *client.DockerCli) inspect.GetRefFunc {
return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().ServiceInspectWithRaw(ctx, ref)
}
}
func inspectTasks(ctx context.Context, dockerCli *client.DockerCli) inspect.GetRefFunc {
return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().TaskInspectWithRaw(ctx, ref)
}
}
func inspectVolume(ctx context.Context, dockerCli *client.DockerCli) inspect.GetRefFunc {
return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().VolumeInspectWithRaw(ctx, ref)
}
}
func inspectAll(ctx context.Context, dockerCli *client.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
var inspectAutodetect = []struct {
ObjectType string
IsSizeSupported bool
ObjectInspector func(string) (interface{}, []byte, error)
}{
{"container", true, inspectContainers(ctx, dockerCli, getSize)},
{"image", true, inspectImages(ctx, dockerCli)},
{"network", false, inspectNetwork(ctx, dockerCli)},
{"volume", false, inspectVolume(ctx, dockerCli)},
{"service", false, inspectService(ctx, dockerCli)},
{"task", false, inspectTasks(ctx, dockerCli)},
{"node", false, inspectNode(ctx, dockerCli)},
}
isErrNotSwarmManager := func(err error) bool {
return strings.Contains(err.Error(), "This node is not a swarm manager")
}
return func(ref string) (interface{}, []byte, error) {
for _, inspectData := range inspectAutodetect {
if typeConstraint != "" && inspectData.ObjectType != typeConstraint {
continue
}
v, raw, err := inspectData.ObjectInspector(ref)
if err != nil {
if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSwarmManager(err)) {
continue
}
return v, raw, err
}
if !inspectData.IsSizeSupported {
fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.ObjectType)
}
return v, raw, err
}
return nil, nil, fmt.Errorf("Error: No such object: %s", ref)
}
} }

View file

@ -11,15 +11,16 @@ parent = "smn_cli"
# inspect # inspect
```markdown ```markdown
Usage: docker inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...] Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on a container, image or task Return low-level information on one or multiple containers, images, volumes,
networks, nodes, services, or tasks identified by name or ID.
-f, --format Format the output using the given go template -f, --format Format the output using the given go template
--help Print usage --help Print usage
-s, --size Display total file sizes if the type is container -s, --size Display total file sizes if the type is container
values are "image" or "container" or "task values are "image" or "container" or "task
--type Return JSON for specified type, (e.g image, container or task) --type Return JSON for specified type
``` ```
By default, this will render all results in a JSON array. If the container and By default, this will render all results in a JSON array. If the container and

View file

@ -176,7 +176,7 @@ func (s *DockerRegistrySuite) TestRemoveImageByDigest(c *check.C) {
_, err = inspectFieldWithError(imageReference, "Id") _, err = inspectFieldWithError(imageReference, "Id")
//unexpected nil err trying to inspect what should be a non-existent image //unexpected nil err trying to inspect what should be a non-existent image
c.Assert(err, checker.NotNil) c.Assert(err, checker.NotNil)
c.Assert(err.Error(), checker.Contains, "No such container, image") c.Assert(err.Error(), checker.Contains, "No such object")
} }
func (s *DockerRegistrySuite) TestBuildByDigest(c *check.C) { func (s *DockerRegistrySuite) TestBuildByDigest(c *check.C) {

View file

@ -65,7 +65,7 @@ func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
result := dockerCmdWithResult("inspect", "-f={{.Name}}", "first_name") result := dockerCmdWithResult("inspect", "-f={{.Name}}", "first_name")
c.Assert(result, icmd.Matches, icmd.Expected{ c.Assert(result, icmd.Matches, icmd.Expected{
ExitCode: 1, ExitCode: 1,
Err: "No such container, image or task: first_name", Err: "No such object: first_name",
}) })
} }

View file

@ -2,23 +2,23 @@
% Docker Community % Docker Community
% JUNE 2014 % JUNE 2014
# NAME # NAME
docker-inspect - Return low-level information on a container or image docker-inspect - Return low-level information on docker objects
# SYNOPSIS # SYNOPSIS
**docker inspect** **docker inspect**
[**--help**] [**--help**]
[**-f**|**--format**[=*FORMAT*]] [**-f**|**--format**[=*FORMAT*]]
[**-s**|**--size**] [**-s**|**--size**]
[**--type**=*container*|*image*] [**--type**=*container*|*image*|*network*|*node*|*service*|*task*|*volume*]
CONTAINER|IMAGE [CONTAINER|IMAGE...] NAME|ID [NAME|ID...]
# DESCRIPTION # DESCRIPTION
This displays all the information available in Docker for a given This displays all the information available in Docker for one or multiple given
container or image. By default, this will render all results in a JSON containers, images, volumes, networks, nodes, services, or tasks. By default,
array. If the container and image have the same name, this will return this will render all results in a JSON array. If the container and image have
container JSON for unspecified type. If a format is specified, the given the same name, this will return container JSON for unspecified type. If a format
template will be executed for each result. is specified, the given template will be executed for each result.
# OPTIONS # OPTIONS
**--help** **--help**
@ -30,8 +30,9 @@ template will be executed for each result.
**-s**, **--size** **-s**, **--size**
Display total file sizes if the type is container. Display total file sizes if the type is container.
**--type**="*container*|*image*" **--type**=*container*|*image*|*network*|*node*|*service*|*task*|*volume*
Return JSON for specified type, permissible values are "image" or "container" Return JSON for specified type, permissible values are "image", "container",
"network", "node", "service", "task", and "volume".
# EXAMPLES # EXAMPLES