Browse code

Merge pull request #23902 from dnephin/inspect-to-cobra

Convert inspect command to Cobra

Alexander Morozov authored on 2016/08/05 03:20:43
Showing 12 changed files
... ...
@@ -2,7 +2,5 @@ package client
2 2
 
3 3
 // Command returns a cli command handler if one exists
4 4
 func (cli *DockerCli) Command(name string) func(...string) error {
5
-	return map[string]func(...string) error{
6
-		"inspect": cli.CmdInspect,
7
-	}[name]
5
+	return map[string]func(...string) error{}[name]
8 6
 }
9 7
deleted file mode 100644
... ...
@@ -1,95 +0,0 @@
1
-package client
2
-
3
-import (
4
-	"fmt"
5
-
6
-	"golang.org/x/net/context"
7
-
8
-	"github.com/docker/docker/api/client/inspect"
9
-	Cli "github.com/docker/docker/cli"
10
-	flag "github.com/docker/docker/pkg/mflag"
11
-	"github.com/docker/engine-api/client"
12
-)
13
-
14
-// CmdInspect displays low-level information on one or more containers, images or tasks.
15
-//
16
-// Usage: docker inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...]
17
-func (cli *DockerCli) CmdInspect(args ...string) error {
18
-	cmd := Cli.Subcmd("inspect", []string{"[OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...]"}, Cli.DockerCommands["inspect"].Description, true)
19
-	tmplStr := cmd.String([]string{"f", "-format"}, "", "Format the output using the given go template")
20
-	inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image, container or task)")
21
-	size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container")
22
-	cmd.Require(flag.Min, 1)
23
-
24
-	cmd.ParseFlags(args, true)
25
-
26
-	if *inspectType != "" && *inspectType != "container" && *inspectType != "image" && *inspectType != "task" {
27
-		return fmt.Errorf("%q is not a valid value for --type", *inspectType)
28
-	}
29
-
30
-	ctx := context.Background()
31
-
32
-	var elementSearcher inspect.GetRefFunc
33
-	switch *inspectType {
34
-	case "container":
35
-		elementSearcher = cli.inspectContainers(ctx, *size)
36
-	case "image":
37
-		elementSearcher = cli.inspectImages(ctx, *size)
38
-	case "task":
39
-		if *size {
40
-			fmt.Fprintln(cli.err, "WARNING: --size ignored for tasks")
41
-		}
42
-		elementSearcher = cli.inspectTasks(ctx)
43
-	default:
44
-		elementSearcher = cli.inspectAll(ctx, *size)
45
-	}
46
-
47
-	return inspect.Inspect(cli.out, cmd.Args(), *tmplStr, elementSearcher)
48
-}
49
-
50
-func (cli *DockerCli) inspectContainers(ctx context.Context, getSize bool) inspect.GetRefFunc {
51
-	return func(ref string) (interface{}, []byte, error) {
52
-		return cli.client.ContainerInspectWithRaw(ctx, ref, getSize)
53
-	}
54
-}
55
-
56
-func (cli *DockerCli) inspectImages(ctx context.Context, getSize bool) inspect.GetRefFunc {
57
-	return func(ref string) (interface{}, []byte, error) {
58
-		return cli.client.ImageInspectWithRaw(ctx, ref, getSize)
59
-	}
60
-}
61
-
62
-func (cli *DockerCli) inspectTasks(ctx context.Context) inspect.GetRefFunc {
63
-	return func(ref string) (interface{}, []byte, error) {
64
-		return cli.client.TaskInspectWithRaw(ctx, ref)
65
-	}
66
-}
67
-
68
-func (cli *DockerCli) inspectAll(ctx context.Context, getSize bool) inspect.GetRefFunc {
69
-	return func(ref string) (interface{}, []byte, error) {
70
-		c, rawContainer, err := cli.client.ContainerInspectWithRaw(ctx, ref, getSize)
71
-		if err != nil {
72
-			// Search for image with that id if a container doesn't exist.
73
-			if client.IsErrContainerNotFound(err) {
74
-				i, rawImage, err := cli.client.ImageInspectWithRaw(ctx, ref, getSize)
75
-				if err != nil {
76
-					if client.IsErrImageNotFound(err) {
77
-						// Search for task with that id if an image doesn't exists.
78
-						t, rawTask, err := cli.client.TaskInspectWithRaw(ctx, ref)
79
-						if err != nil {
80
-							return nil, nil, fmt.Errorf("Error: No such image, container or task: %s", ref)
81
-						}
82
-						if getSize {
83
-							fmt.Fprintln(cli.err, "WARNING: --size ignored for tasks")
84
-						}
85
-						return t, rawTask, nil
86
-					}
87
-					return nil, nil, err
88
-				}
89
-				return i, rawImage, nil
90
-			}
91
-			return nil, nil, err
92
-		}
93
-		return c, rawContainer, nil
94
-	}
95
-}
96 1
new file mode 100644
... ...
@@ -0,0 +1,103 @@
0
+package system
1
+
2
+import (
3
+	"fmt"
4
+	"strings"
5
+
6
+	"golang.org/x/net/context"
7
+
8
+	"github.com/docker/docker/api/client"
9
+	"github.com/docker/docker/api/client/inspect"
10
+	"github.com/docker/docker/cli"
11
+	apiclient "github.com/docker/engine-api/client"
12
+	"github.com/spf13/cobra"
13
+)
14
+
15
+type inspectOptions struct {
16
+	format      string
17
+	inspectType string
18
+	size        bool
19
+	ids         []string
20
+}
21
+
22
+// NewInspectCommand creates a new cobra.Command for `docker inspect`
23
+func NewInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
24
+	var opts inspectOptions
25
+
26
+	cmd := &cobra.Command{
27
+		Use:   "inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...]",
28
+		Short: "Return low-level information on a container, image or task",
29
+		Args:  cli.RequiresMinArgs(1),
30
+		RunE: func(cmd *cobra.Command, args []string) error {
31
+			opts.ids = args
32
+			return runInspect(dockerCli, opts)
33
+		},
34
+	}
35
+
36
+	flags := cmd.Flags()
37
+	flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
38
+	flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type, (e.g image, container or task)")
39
+	flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")
40
+
41
+	return cmd
42
+}
43
+
44
+func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
45
+	ctx := context.Background()
46
+	client := dockerCli.Client()
47
+
48
+	var getRefFunc inspect.GetRefFunc
49
+	switch opts.inspectType {
50
+	case "container":
51
+		getRefFunc = func(ref string) (interface{}, []byte, error) {
52
+			return client.ContainerInspectWithRaw(ctx, ref, opts.size)
53
+		}
54
+	case "image":
55
+		getRefFunc = func(ref string) (interface{}, []byte, error) {
56
+			return client.ImageInspectWithRaw(ctx, ref, opts.size)
57
+		}
58
+	case "task":
59
+		if opts.size {
60
+			fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
61
+		}
62
+		getRefFunc = func(ref string) (interface{}, []byte, error) {
63
+			return client.TaskInspectWithRaw(ctx, ref)
64
+		}
65
+	case "":
66
+		getRefFunc = inspectAll(ctx, dockerCli, opts.size)
67
+	default:
68
+		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
69
+	}
70
+
71
+	return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, getRefFunc)
72
+}
73
+
74
+func inspectAll(ctx context.Context, dockerCli *client.DockerCli, getSize bool) inspect.GetRefFunc {
75
+	client := dockerCli.Client()
76
+
77
+	return func(ref string) (interface{}, []byte, error) {
78
+		c, rawContainer, err := client.ContainerInspectWithRaw(ctx, ref, getSize)
79
+		if err == nil || !apiclient.IsErrNotFound(err) {
80
+			return c, rawContainer, err
81
+		}
82
+		// Search for image with that id if a container doesn't exist.
83
+		i, rawImage, err := client.ImageInspectWithRaw(ctx, ref, getSize)
84
+		if err == nil || !apiclient.IsErrNotFound(err) {
85
+			return i, rawImage, err
86
+		}
87
+
88
+		// Search for task with that id if an image doesn't exist.
89
+		t, rawTask, err := client.TaskInspectWithRaw(ctx, ref)
90
+		if err == nil || !(apiclient.IsErrNotFound(err) || isErrorNoSwarmMode(err)) {
91
+			if getSize {
92
+				fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
93
+			}
94
+			return t, rawTask, err
95
+		}
96
+		return nil, nil, fmt.Errorf("Error: No such container, image or task: %s", ref)
97
+	}
98
+}
99
+
100
+func isErrorNoSwarmMode(err error) bool {
101
+	return strings.Contains(err.Error(), "This node is not a swarm manager")
102
+}
... ...
@@ -83,6 +83,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor {
83 83
 		image.NewTagCommand(dockerCli),
84 84
 		network.NewNetworkCommand(dockerCli),
85 85
 		system.NewEventsCommand(dockerCli),
86
+		system.NewInspectCommand(dockerCli),
86 87
 		registry.NewLoginCommand(dockerCli),
87 88
 		registry.NewLogoutCommand(dockerCli),
88 89
 		system.NewVersionCommand(dockerCli),
... ...
@@ -7,9 +7,7 @@ type Command struct {
7 7
 }
8 8
 
9 9
 // DockerCommandUsage lists the top level docker commands and their short usage
10
-var DockerCommandUsage = []Command{
11
-	{"inspect", "Return low-level information on a container, image or task"},
12
-}
10
+var DockerCommandUsage = []Command{}
13 11
 
14 12
 // DockerCommands stores all the docker command
15 13
 var DockerCommands = make(map[string]Command)
... ...
@@ -176,7 +176,7 @@ func (s *DockerRegistrySuite) TestRemoveImageByDigest(c *check.C) {
176 176
 	_, err = inspectFieldWithError(imageReference, "Id")
177 177
 	//unexpected nil err trying to inspect what should be a non-existent image
178 178
 	c.Assert(err, checker.NotNil)
179
-	c.Assert(err.Error(), checker.Contains, "No such image")
179
+	c.Assert(err.Error(), checker.Contains, "No such container, image")
180 180
 }
181 181
 
182 182
 func (s *DockerRegistrySuite) TestBuildByDigest(c *check.C) {
... ...
@@ -326,7 +326,7 @@ func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) {
326 326
 	}
327 327
 
328 328
 	// make sure the container is not running
329
-	runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top")
329
+	runningOut, err := s.d.Cmd("inspect", "--format={{.State.Running}}", "top")
330 330
 	if err != nil {
331 331
 		c.Fatalf("Could not inspect on container: %s, %v", out, err)
332 332
 	}
... ...
@@ -2196,7 +2196,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) {
2196 2196
 	}
2197 2197
 
2198 2198
 	// container should be running.
2199
-	out, err = s.d.Cmd("inspect", "--format='{{.State.Running}}'", id)
2199
+	out, err = s.d.Cmd("inspect", "--format={{.State.Running}}", id)
2200 2200
 	c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
2201 2201
 	out = strings.TrimSpace(out)
2202 2202
 	if out != "true" {
... ...
@@ -353,7 +353,7 @@ func (s *DockerExternalGraphdriverSuite) testExternalGraphDriver(name string, ex
353 353
 
354 354
 	err = s.d.Restart("-s", name)
355 355
 
356
-	out, err = s.d.Cmd("inspect", "--format='{{.GraphDriver.Name}}'", "graphtest")
356
+	out, err = s.d.Cmd("inspect", "--format={{.GraphDriver.Name}}", "graphtest")
357 357
 	c.Assert(err, check.IsNil, check.Commentf(out))
358 358
 	c.Assert(strings.TrimSpace(out), check.Equals, name)
359 359
 
... ...
@@ -73,10 +73,10 @@ func (s *DockerSuite) TestHealth(c *check.C) {
73 73
 
74 74
 	// Inspect the options
75 75
 	out, _ = dockerCmd(c, "inspect",
76
-		"--format='timeout={{.Config.Healthcheck.Timeout}} "+
76
+		"--format=timeout={{.Config.Healthcheck.Timeout}} "+
77 77
 			"interval={{.Config.Healthcheck.Interval}} "+
78 78
 			"retries={{.Config.Healthcheck.Retries}} "+
79
-			"test={{.Config.Healthcheck.Test}}'", name)
79
+			"test={{.Config.Healthcheck.Test}}", name)
80 80
 	c.Check(out, checker.Equals, "timeout=30s interval=1s retries=0 test=[CMD-SHELL cat /status]\n")
81 81
 
82 82
 	// Start
... ...
@@ -85,7 +85,7 @@ func (s *DockerSuite) TestInspectTypeFlagContainer(c *check.C) {
85 85
 
86 86
 	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
87 87
 
88
-	formatStr := "--format='{{.State.Running}}'"
88
+	formatStr := "--format={{.State.Running}}"
89 89
 	out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
90 90
 	c.Assert(out, checker.Equals, "true\n") // not a container JSON
91 91
 }
... ...
@@ -137,7 +137,7 @@ func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
137 137
 	c.Assert(err, checker.IsNil, check.Commentf("failed to inspect size of the image: %s, %v", out, err))
138 138
 
139 139
 	//now see if the size turns out to be the same
140
-	formatStr := fmt.Sprintf("--format='{{eq .Size %d}}'", size)
140
+	formatStr := fmt.Sprintf("--format={{eq .Size %d}}", size)
141 141
 	out, _ = dockerCmd(c, "inspect", formatStr, imageTest)
142 142
 	result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n"))
143 143
 	c.Assert(err, checker.IsNil)
... ...
@@ -159,7 +159,7 @@ func (s *DockerSuite) TestInspectContainerFilterInt(c *check.C) {
159 159
 	c.Assert(err, checker.IsNil, check.Commentf("failed to inspect exitcode of the container: %s, %v", out, err))
160 160
 
161 161
 	//now get the exit code to verify
162
-	formatStr := fmt.Sprintf("--format='{{eq .State.ExitCode %d}}'", exitCode)
162
+	formatStr := fmt.Sprintf("--format={{eq .State.ExitCode %d}}", exitCode)
163 163
 	out, _ = dockerCmd(c, "inspect", formatStr, id)
164 164
 	result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n"))
165 165
 	c.Assert(err, checker.IsNil)
... ...
@@ -312,7 +312,7 @@ func (s *DockerSuite) TestInspectNoSizeFlagContainer(c *check.C) {
312 312
 
313 313
 	runSleepingContainer(c, "--name=busybox", "-d")
314 314
 
315
-	formatStr := "--format='{{.SizeRw}},{{.SizeRootFs}}'"
315
+	formatStr := "--format={{.SizeRw}},{{.SizeRootFs}}"
316 316
 	out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
317 317
 	c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Exepcted not to display size info: %s", out))
318 318
 }
... ...
@@ -356,7 +356,7 @@ func (s *DockerSuite) TestInspectTemplateError(c *check.C) {
356 356
 
357 357
 func (s *DockerSuite) TestInspectJSONFields(c *check.C) {
358 358
 	runSleepingContainer(c, "--name=busybox", "-d")
359
-	out, _, err := dockerCmdWithError("inspect", "--type=container", "--format='{{.HostConfig.Dns}}'", "busybox")
359
+	out, _, err := dockerCmdWithError("inspect", "--type=container", "--format={{.HostConfig.Dns}}", "busybox")
360 360
 
361 361
 	c.Assert(err, check.IsNil)
362 362
 	c.Assert(out, checker.Equals, "[]\n")
... ...
@@ -63,7 +63,7 @@ func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
63 63
 
64 64
 	name, err := inspectFieldWithError("first_name", "Name")
65 65
 	c.Assert(err, checker.NotNil, check.Commentf(name))
66
-	c.Assert(err.Error(), checker.Contains, "No such image, container or task: first_name")
66
+	c.Assert(err.Error(), checker.Contains, "No such container, image or task: first_name")
67 67
 }
68 68
 
69 69
 func (s *DockerSuite) TestRenameInvalidName(c *check.C) {
... ...
@@ -129,7 +129,7 @@ func (s *DockerSuite) TestRenameContainerWithLinkedContainer(c *check.C) {
129 129
 	db1, _ := dockerCmd(c, "run", "--name", "db1", "-d", "busybox", "top")
130 130
 	dockerCmd(c, "run", "--name", "app1", "-d", "--link", "db1:/mysql", "busybox", "top")
131 131
 	dockerCmd(c, "rename", "app1", "app2")
132
-	out, _, err := dockerCmdWithError("inspect", "--format='{{ .Id }}'", "app2/mysql")
132
+	out, _, err := dockerCmdWithError("inspect", "--format={{ .Id }}", "app2/mysql")
133 133
 	c.Assert(err, checker.IsNil)
134 134
 	c.Assert(strings.TrimSpace(out), checker.Equals, strings.TrimSpace(db1))
135 135
 }
... ...
@@ -45,7 +45,7 @@ func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *check.C) {
45 45
 	user := s.findUser(c, "userns")
46 46
 	c.Assert(uidgid[0], checker.Equals, user)
47 47
 
48
-	pid, err := s.d.Cmd("inspect", "--format='{{.State.Pid}}'", "userns")
48
+	pid, err := s.d.Cmd("inspect", "--format={{.State.Pid}}", "userns")
49 49
 	c.Assert(err, checker.IsNil, check.Commentf("Could not inspect running container: out: %q", pid))
50 50
 	// check the uid and gid maps for the PID to ensure root is remapped
51 51
 	// (cmd = cat /proc/<pid>/uid_map | grep -E '0\s+9999\s+1')