فهرست منبع

Merge pull request #13187 from shishir-a412ed/docker_inspect_issue

Flag Addition: --type flag added for docker inspect command
Sebastiaan van Stijn 10 سال پیش
والد
کامیت
98f988f62c
5فایلهای تغییر یافته به همراه171 افزوده شده و 12 حذف شده
  1. 31 5
      api/client/inspect.go
  2. 6 1
      contrib/completion/bash/docker
  3. 3 0
      docs/reference/commandline/inspect.md
  4. 109 0
      integration-cli/docker_cli_inspect_test.go
  5. 22 6
      man/docker-inspect.1.md

+ 31 - 5
api/client/inspect.go

@@ -18,42 +18,68 @@ import (
 func (cli *DockerCli) CmdInspect(args ...string) error {
 func (cli *DockerCli) CmdInspect(args ...string) error {
 	cmd := cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, "Return low-level information on a container or image", true)
 	cmd := cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, "Return low-level information on a container or image", 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)")
+
 	cmd.Require(flag.Min, 1)
 	cmd.Require(flag.Min, 1)
 
 
 	cmd.ParseFlags(args, true)
 	cmd.ParseFlags(args, true)
 
 
 	var tmpl *template.Template
 	var tmpl *template.Template
+	var err error
+	var obj []byte
+
 	if *tmplStr != "" {
 	if *tmplStr != "" {
-		var err error
 		if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
 		if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
 			return StatusError{StatusCode: 64,
 			return StatusError{StatusCode: 64,
 				Status: "Template parsing error: " + err.Error()}
 				Status: "Template parsing error: " + err.Error()}
 		}
 		}
 	}
 	}
 
 
+	if *inspectType != "" && *inspectType != "container" && *inspectType != "image" {
+		return fmt.Errorf("%q is not a valid value for --type", *inspectType)
+	}
+
 	indented := new(bytes.Buffer)
 	indented := new(bytes.Buffer)
 	indented.WriteString("[\n")
 	indented.WriteString("[\n")
 	status := 0
 	status := 0
 	isImage := false
 	isImage := false
 
 
 	for _, name := range cmd.Args() {
 	for _, name := range cmd.Args() {
-		obj, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
-		if err != nil {
+
+		if *inspectType == "" || *inspectType == "container" {
+			obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
+			if err != nil && *inspectType == "container" {
+				if strings.Contains(err.Error(), "No such") {
+					fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)
+				} else {
+					fmt.Fprintf(cli.err, "%s", err)
+				}
+				status = 1
+				continue
+			}
+		}
+
+		if obj == nil && (*inspectType == "" || *inspectType == "image") {
 			obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
 			obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
 			isImage = true
 			isImage = true
 			if err != nil {
 			if err != nil {
 				if strings.Contains(err.Error(), "No such") {
 				if strings.Contains(err.Error(), "No such") {
-					fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
+					if *inspectType == "" {
+						fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
+					} else {
+						fmt.Fprintf(cli.err, "Error: No such image: %s\n", name)
+					}
 				} else {
 				} else {
 					fmt.Fprintf(cli.err, "%s", err)
 					fmt.Fprintf(cli.err, "%s", err)
 				}
 				}
 				status = 1
 				status = 1
 				continue
 				continue
 			}
 			}
+
 		}
 		}
 
 
 		if tmpl == nil {
 		if tmpl == nil {
-			if err = json.Indent(indented, obj, "", "    "); err != nil {
+			if err := json.Indent(indented, obj, "", "    "); err != nil {
 				fmt.Fprintf(cli.err, "%s\n", err)
 				fmt.Fprintf(cli.err, "%s\n", err)
 				status = 1
 				status = 1
 				continue
 				continue

+ 6 - 1
contrib/completion/bash/docker

@@ -527,11 +527,16 @@ _docker_inspect() {
 		--format|-f)
 		--format|-f)
 			return
 			return
 			;;
 			;;
+		--type)
+                     COMPREPLY=( $( compgen -W "image container" -- "$cur" ) )
+                     return
+                        ;;
+
 	esac
 	esac
 
 
 	case "$cur" in
 	case "$cur" in
 		-*)
 		-*)
-			COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) )
+			COMPREPLY=( $( compgen -W "--format -f --type --help" -- "$cur" ) )
 			;;
 			;;
 		*)
 		*)
 			__docker_containers_and_images
 			__docker_containers_and_images

+ 3 - 0
docs/reference/commandline/inspect.md

@@ -17,6 +17,9 @@ weight=1
 
 
       -f, --format=""    Format the output using the given go template
       -f, --format=""    Format the output using the given go template
 
 
+     --type=container|image  Return JSON for specified type, permissible 
+                             values are "image" or "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.
 
 

+ 109 - 0
integration-cli/docker_cli_inspect_test.go

@@ -38,6 +38,115 @@ func (s *DockerSuite) TestInspectInt64(c *check.C) {
 	}
 	}
 }
 }
 
 
+func (s *DockerSuite) TestInspectDefault(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fetch the container JSON.
+	//If the container JSON is not available, it will go for the image JSON.
+
+	runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "true")
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+
+	inspectCmd := exec.Command(dockerBinary, "inspect", "busybox")
+
+	_, exitCode, err := runCommandWithOutput(inspectCmd)
+	if exitCode != 0 || err != nil {
+		c.Fatalf("failed to inspect container: %s, %v", out, err)
+	}
+}
+
+func (s *DockerSuite) TestInspectTypeFlagContainer(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fetch container
+	//JSON State.Running field. If the field is true, it's a container.
+
+	runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "top")
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+
+	formatStr := fmt.Sprintf("--format='{{.State.Running}}'")
+	inspectCmd := exec.Command(dockerBinary, "inspect", "--type=container", formatStr, "busybox")
+
+	out, exitCode, err := runCommandWithOutput(inspectCmd)
+	if exitCode != 0 || err != nil {
+		c.Fatalf("failed to inspect container: %s, %v", out, err)
+	}
+
+	if out != "true\n" {
+		c.Fatal("not a container JSON")
+	}
+}
+
+func (s *DockerSuite) TestInspectTypeFlagWithNoContainer(c *check.C) {
+
+	//Run this test on an image named busybox. docker inspect will try to fetch container
+	//JSON. Since there is no container named busybox and --type=container, docker inspect will
+	//not try to get the image JSON. It will throw an error.
+
+	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+
+	inspectCmd := exec.Command(dockerBinary, "inspect", "--type=container", "busybox")
+
+	_, exitCode, err := runCommandWithOutput(inspectCmd)
+	if exitCode == 0 || err == nil {
+		c.Fatalf("docker inspect should have failed, as there is no container named busybox")
+	}
+}
+
+func (s *DockerSuite) TestInspectTypeFlagWithImage(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fetch image
+	//JSON as --type=image. if there is no image with name busybox, docker inspect
+	//will throw an error.
+
+	runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "true")
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+
+	inspectCmd := exec.Command(dockerBinary, "inspect", "--type=image", "busybox")
+
+	out, exitCode, err := runCommandWithOutput(inspectCmd)
+	if exitCode != 0 || err != nil {
+		c.Fatalf("failed to inspect image: %s, %v", out, err)
+	}
+
+	if strings.Contains(out, "State") {
+		c.Fatal("not an image JSON")
+	}
+
+}
+
+func (s *DockerSuite) TestInspectTypeFlagWithInvalidValue(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fail
+	//as --type=foobar is not a valid value for the flag.
+
+	runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "true")
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+
+	inspectCmd := exec.Command(dockerBinary, "inspect", "--type=foobar", "busybox")
+
+	out, exitCode, err := runCommandWithOutput(inspectCmd)
+	if exitCode != 0 || err != nil {
+		if !strings.Contains(out, "not a valid value for --type") {
+			c.Fatalf("failed to inspect image: %s, %v", out, err)
+		}
+	}
+}
+
 func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
 func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
 	imageTest := "emptyfs"
 	imageTest := "emptyfs"
 	out, err := inspectField(imageTest, "Size")
 	out, err := inspectField(imageTest, "Size")

+ 22 - 6
man/docker-inspect.1.md

@@ -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*]]
+[**--type**=*container*|*image*]
 CONTAINER|IMAGE [CONTAINER|IMAGE...]
 CONTAINER|IMAGE [CONTAINER|IMAGE...]
 
 
 # DESCRIPTION
 # DESCRIPTION
@@ -24,14 +25,29 @@ each result.
 **-f**, **--format**=""
 **-f**, **--format**=""
     Format the output using the given go template.
     Format the output using the given go template.
 
 
+**--type**=*container*|*image*
+    Return JSON for specified type, permissible values are "image" or "container"
+
 # EXAMPLES
 # EXAMPLES
 
 
+Getting information on an image where image name conflict with the container name,
+e,g both image and container are named rhel7.
+
+    $ docker inspect --type=image rhel7
+    [
+    {
+     "Id": "fe01a428b9d9de35d29531e9994157978e8c48fa693e1bf1d221dffbbb67b170",
+     "Parent": "10acc31def5d6f249b548e01e8ffbaccfd61af0240c17315a7ad393d022c5ca2",
+     ....
+    }
+    ]
+
 ## Getting information on a container
 ## Getting information on a container
 
 
 To get information on a container use its ID or instance name:
 To get information on a container use its ID or instance name:
 
 
     $ docker inspect d2cc496561d6
     $ docker inspect d2cc496561d6
-[{
+    [{
     "Id": "d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47",
     "Id": "d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47",
     "Created": "2015-06-08T16:18:02.505155285Z",
     "Created": "2015-06-08T16:18:02.505155285Z",
     "Path": "bash",
     "Path": "bash",
@@ -161,8 +177,8 @@ To get information on a container use its ID or instance name:
         "CpuShares": 0,
         "CpuShares": 0,
         "Cpuset": ""
         "Cpuset": ""
     }
     }
-}
-]
+    }
+    ]
 ## Getting the IP address of a container instance
 ## Getting the IP address of a container instance
 
 
 To get the IP address of a container use:
 To get the IP address of a container use:
@@ -188,7 +204,7 @@ Use an image's ID or name (e.g., repository/name[:tag]) to get information
 on it.
 on it.
 
 
     $ docker inspect ded7cd95e059
     $ docker inspect ded7cd95e059
-[{
+    [{
     "Id": "ded7cd95e059788f2586a51c275a4f151653779d6a7f4dad77c2bd34601d94e4",
     "Id": "ded7cd95e059788f2586a51c275a4f151653779d6a7f4dad77c2bd34601d94e4",
     "Parent": "48ecf305d2cf7046c1f5f8fcbcd4994403173441d4a7f125b1bb0ceead9de731",
     "Parent": "48ecf305d2cf7046c1f5f8fcbcd4994403173441d4a7f125b1bb0ceead9de731",
     "Comment": "",
     "Comment": "",
@@ -258,8 +274,8 @@ on it.
             "DeviceSize": "171798691840"
             "DeviceSize": "171798691840"
         }
         }
     }
     }
-}
-]
+    }
+    ]
 
 
 # HISTORY
 # HISTORY
 April 2014, originally compiled by William Henry (whenry at redhat dot com)
 April 2014, originally compiled by William Henry (whenry at redhat dot com)