Signed-off-by: Shishir Mahajan <shishir.mahajan@redhat.com>
| ... | ... |
@@ -18,42 +18,68 @@ import ( |
| 18 | 18 |
func (cli *DockerCli) CmdInspect(args ...string) error {
|
| 19 | 19 |
cmd := cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, "Return low-level information on a container or image", true)
|
| 20 | 20 |
tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
|
| 21 |
+ inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
|
|
| 22 |
+ |
|
| 21 | 23 |
cmd.Require(flag.Min, 1) |
| 22 | 24 |
|
| 23 | 25 |
cmd.ParseFlags(args, true) |
| 24 | 26 |
|
| 25 | 27 |
var tmpl *template.Template |
| 28 |
+ var err error |
|
| 29 |
+ var obj []byte |
|
| 30 |
+ |
|
| 26 | 31 |
if *tmplStr != "" {
|
| 27 |
- var err error |
|
| 28 | 32 |
if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
|
| 29 | 33 |
return StatusError{StatusCode: 64,
|
| 30 | 34 |
Status: "Template parsing error: " + err.Error()} |
| 31 | 35 |
} |
| 32 | 36 |
} |
| 33 | 37 |
|
| 38 |
+ if *inspectType != "" && *inspectType != "container" && *inspectType != "image" {
|
|
| 39 |
+ return fmt.Errorf("%q is not a valid value for --type", *inspectType)
|
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 34 | 42 |
indented := new(bytes.Buffer) |
| 35 | 43 |
indented.WriteString("[\n")
|
| 36 | 44 |
status := 0 |
| 37 | 45 |
isImage := false |
| 38 | 46 |
|
| 39 | 47 |
for _, name := range cmd.Args() {
|
| 40 |
- obj, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
|
|
| 41 |
- if err != nil {
|
|
| 48 |
+ |
|
| 49 |
+ if *inspectType == "" || *inspectType == "container" {
|
|
| 50 |
+ obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
|
|
| 51 |
+ if err != nil && *inspectType == "container" {
|
|
| 52 |
+ if strings.Contains(err.Error(), "No such") {
|
|
| 53 |
+ fmt.Fprintf(cli.err, "Error: No such container: %s\n", name) |
|
| 54 |
+ } else {
|
|
| 55 |
+ fmt.Fprintf(cli.err, "%s", err) |
|
| 56 |
+ } |
|
| 57 |
+ status = 1 |
|
| 58 |
+ continue |
|
| 59 |
+ } |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ if obj == nil && (*inspectType == "" || *inspectType == "image") {
|
|
| 42 | 63 |
obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
|
| 43 | 64 |
isImage = true |
| 44 | 65 |
if err != nil {
|
| 45 | 66 |
if strings.Contains(err.Error(), "No such") {
|
| 46 |
- fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name) |
|
| 67 |
+ if *inspectType == "" {
|
|
| 68 |
+ fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name) |
|
| 69 |
+ } else {
|
|
| 70 |
+ fmt.Fprintf(cli.err, "Error: No such image: %s\n", name) |
|
| 71 |
+ } |
|
| 47 | 72 |
} else {
|
| 48 | 73 |
fmt.Fprintf(cli.err, "%s", err) |
| 49 | 74 |
} |
| 50 | 75 |
status = 1 |
| 51 | 76 |
continue |
| 52 | 77 |
} |
| 78 |
+ |
|
| 53 | 79 |
} |
| 54 | 80 |
|
| 55 | 81 |
if tmpl == nil {
|
| 56 |
- if err = json.Indent(indented, obj, "", " "); err != nil {
|
|
| 82 |
+ if err := json.Indent(indented, obj, "", " "); err != nil {
|
|
| 57 | 83 |
fmt.Fprintf(cli.err, "%s\n", err) |
| 58 | 84 |
status = 1 |
| 59 | 85 |
continue |
| ... | ... |
@@ -527,11 +527,16 @@ _docker_inspect() {
|
| 527 | 527 |
--format|-f) |
| 528 | 528 |
return |
| 529 | 529 |
;; |
| 530 |
+ --type) |
|
| 531 |
+ COMPREPLY=( $( compgen -W "image container" -- "$cur" ) ) |
|
| 532 |
+ return |
|
| 533 |
+ ;; |
|
| 534 |
+ |
|
| 530 | 535 |
esac |
| 531 | 536 |
|
| 532 | 537 |
case "$cur" in |
| 533 | 538 |
-*) |
| 534 |
- COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) |
|
| 539 |
+ COMPREPLY=( $( compgen -W "--format -f --type --help" -- "$cur" ) ) |
|
| 535 | 540 |
;; |
| 536 | 541 |
*) |
| 537 | 542 |
__docker_containers_and_images |
| ... | ... |
@@ -17,6 +17,9 @@ weight=1 |
| 17 | 17 |
|
| 18 | 18 |
-f, --format="" Format the output using the given go template |
| 19 | 19 |
|
| 20 |
+ --type=container|image Return JSON for specified type, permissible |
|
| 21 |
+ values are "image" or "container" |
|
| 22 |
+ |
|
| 20 | 23 |
By default, this will render all results in a JSON array. If a format is |
| 21 | 24 |
specified, the given template will be executed for each result. |
| 22 | 25 |
|
| ... | ... |
@@ -38,6 +38,115 @@ func (s *DockerSuite) TestInspectInt64(c *check.C) {
|
| 38 | 38 |
} |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
+func (s *DockerSuite) TestInspectDefault(c *check.C) {
|
|
| 42 |
+ |
|
| 43 |
+ //Both the container and image are named busybox. docker inspect will fetch the container JSON. |
|
| 44 |
+ //If the container JSON is not available, it will go for the image JSON. |
|
| 45 |
+ |
|
| 46 |
+ runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "true") |
|
| 47 |
+ out, _, _, err := runCommandWithStdoutStderr(runCmd) |
|
| 48 |
+ if err != nil {
|
|
| 49 |
+ c.Fatalf("failed to run container: %v, output: %q", err, out)
|
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", "busybox") |
|
| 53 |
+ |
|
| 54 |
+ _, exitCode, err := runCommandWithOutput(inspectCmd) |
|
| 55 |
+ if exitCode != 0 || err != nil {
|
|
| 56 |
+ c.Fatalf("failed to inspect container: %s, %v", out, err)
|
|
| 57 |
+ } |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+func (s *DockerSuite) TestInspectTypeFlagContainer(c *check.C) {
|
|
| 61 |
+ |
|
| 62 |
+ //Both the container and image are named busybox. docker inspect will fetch container |
|
| 63 |
+ //JSON State.Running field. If the field is true, it's a container. |
|
| 64 |
+ |
|
| 65 |
+ runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "top") |
|
| 66 |
+ out, _, _, err := runCommandWithStdoutStderr(runCmd) |
|
| 67 |
+ if err != nil {
|
|
| 68 |
+ c.Fatalf("failed to run container: %v, output: %q", err, out)
|
|
| 69 |
+ } |
|
| 70 |
+ |
|
| 71 |
+ formatStr := fmt.Sprintf("--format='{{.State.Running}}'")
|
|
| 72 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", "--type=container", formatStr, "busybox") |
|
| 73 |
+ |
|
| 74 |
+ out, exitCode, err := runCommandWithOutput(inspectCmd) |
|
| 75 |
+ if exitCode != 0 || err != nil {
|
|
| 76 |
+ c.Fatalf("failed to inspect container: %s, %v", out, err)
|
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ if out != "true\n" {
|
|
| 80 |
+ c.Fatal("not a container JSON")
|
|
| 81 |
+ } |
|
| 82 |
+} |
|
| 83 |
+ |
|
| 84 |
+func (s *DockerSuite) TestInspectTypeFlagWithNoContainer(c *check.C) {
|
|
| 85 |
+ |
|
| 86 |
+ //Run this test on an image named busybox. docker inspect will try to fetch container |
|
| 87 |
+ //JSON. Since there is no container named busybox and --type=container, docker inspect will |
|
| 88 |
+ //not try to get the image JSON. It will throw an error. |
|
| 89 |
+ |
|
| 90 |
+ runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") |
|
| 91 |
+ out, _, _, err := runCommandWithStdoutStderr(runCmd) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ c.Fatalf("failed to run container: %v, output: %q", err, out)
|
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", "--type=container", "busybox") |
|
| 97 |
+ |
|
| 98 |
+ _, exitCode, err := runCommandWithOutput(inspectCmd) |
|
| 99 |
+ if exitCode == 0 || err == nil {
|
|
| 100 |
+ c.Fatalf("docker inspect should have failed, as there is no container named busybox")
|
|
| 101 |
+ } |
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+func (s *DockerSuite) TestInspectTypeFlagWithImage(c *check.C) {
|
|
| 105 |
+ |
|
| 106 |
+ //Both the container and image are named busybox. docker inspect will fetch image |
|
| 107 |
+ //JSON as --type=image. if there is no image with name busybox, docker inspect |
|
| 108 |
+ //will throw an error. |
|
| 109 |
+ |
|
| 110 |
+ runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "true") |
|
| 111 |
+ out, _, _, err := runCommandWithStdoutStderr(runCmd) |
|
| 112 |
+ if err != nil {
|
|
| 113 |
+ c.Fatalf("failed to run container: %v, output: %q", err, out)
|
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", "--type=image", "busybox") |
|
| 117 |
+ |
|
| 118 |
+ out, exitCode, err := runCommandWithOutput(inspectCmd) |
|
| 119 |
+ if exitCode != 0 || err != nil {
|
|
| 120 |
+ c.Fatalf("failed to inspect image: %s, %v", out, err)
|
|
| 121 |
+ } |
|
| 122 |
+ |
|
| 123 |
+ if strings.Contains(out, "State") {
|
|
| 124 |
+ c.Fatal("not an image JSON")
|
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+} |
|
| 128 |
+ |
|
| 129 |
+func (s *DockerSuite) TestInspectTypeFlagWithInvalidValue(c *check.C) {
|
|
| 130 |
+ |
|
| 131 |
+ //Both the container and image are named busybox. docker inspect will fail |
|
| 132 |
+ //as --type=foobar is not a valid value for the flag. |
|
| 133 |
+ |
|
| 134 |
+ runCmd := exec.Command(dockerBinary, "run", "--name=busybox", "-d", "busybox", "true") |
|
| 135 |
+ out, _, _, err := runCommandWithStdoutStderr(runCmd) |
|
| 136 |
+ if err != nil {
|
|
| 137 |
+ c.Fatalf("failed to run container: %v, output: %q", err, out)
|
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", "--type=foobar", "busybox") |
|
| 141 |
+ |
|
| 142 |
+ out, exitCode, err := runCommandWithOutput(inspectCmd) |
|
| 143 |
+ if exitCode != 0 || err != nil {
|
|
| 144 |
+ if !strings.Contains(out, "not a valid value for --type") {
|
|
| 145 |
+ c.Fatalf("failed to inspect image: %s, %v", out, err)
|
|
| 146 |
+ } |
|
| 147 |
+ } |
|
| 148 |
+} |
|
| 149 |
+ |
|
| 41 | 150 |
func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
|
| 42 | 151 |
imageTest := "emptyfs" |
| 43 | 152 |
out, err := inspectField(imageTest, "Size") |
| ... | ... |
@@ -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 |
+[**--type**=*container*|*image*] |
|
| 11 | 12 |
CONTAINER|IMAGE [CONTAINER|IMAGE...] |
| 12 | 13 |
|
| 13 | 14 |
# DESCRIPTION |
| ... | ... |
@@ -24,14 +25,29 @@ each result. |
| 24 | 24 |
**-f**, **--format**="" |
| 25 | 25 |
Format the output using the given go template. |
| 26 | 26 |
|
| 27 |
+**--type**=*container*|*image* |
|
| 28 |
+ Return JSON for specified type, permissible values are "image" or "container" |
|
| 29 |
+ |
|
| 27 | 30 |
# EXAMPLES |
| 28 | 31 |
|
| 32 |
+Getting information on an image where image name conflict with the container name, |
|
| 33 |
+e,g both image and container are named rhel7. |
|
| 34 |
+ |
|
| 35 |
+ $ docker inspect --type=image rhel7 |
|
| 36 |
+ [ |
|
| 37 |
+ {
|
|
| 38 |
+ "Id": "fe01a428b9d9de35d29531e9994157978e8c48fa693e1bf1d221dffbbb67b170", |
|
| 39 |
+ "Parent": "10acc31def5d6f249b548e01e8ffbaccfd61af0240c17315a7ad393d022c5ca2", |
|
| 40 |
+ .... |
|
| 41 |
+ } |
|
| 42 |
+ ] |
|
| 43 |
+ |
|
| 29 | 44 |
## Getting information on a container |
| 30 | 45 |
|
| 31 | 46 |
To get information on a container use its ID or instance name: |
| 32 | 47 |
|
| 33 | 48 |
$ docker inspect d2cc496561d6 |
| 34 |
-[{
|
|
| 49 |
+ [{
|
|
| 35 | 50 |
"Id": "d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47", |
| 36 | 51 |
"Created": "2015-06-08T16:18:02.505155285Z", |
| 37 | 52 |
"Path": "bash", |
| ... | ... |
@@ -161,8 +177,8 @@ To get information on a container use its ID or instance name: |
| 161 | 161 |
"CpuShares": 0, |
| 162 | 162 |
"Cpuset": "" |
| 163 | 163 |
} |
| 164 |
-} |
|
| 165 |
-] |
|
| 164 |
+ } |
|
| 165 |
+ ] |
|
| 166 | 166 |
## Getting the IP address of a container instance |
| 167 | 167 |
|
| 168 | 168 |
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 |
| 188 | 188 |
on it. |
| 189 | 189 |
|
| 190 | 190 |
$ docker inspect ded7cd95e059 |
| 191 |
-[{
|
|
| 191 |
+ [{
|
|
| 192 | 192 |
"Id": "ded7cd95e059788f2586a51c275a4f151653779d6a7f4dad77c2bd34601d94e4", |
| 193 | 193 |
"Parent": "48ecf305d2cf7046c1f5f8fcbcd4994403173441d4a7f125b1bb0ceead9de731", |
| 194 | 194 |
"Comment": "", |
| ... | ... |
@@ -258,8 +274,8 @@ on it. |
| 258 | 258 |
"DeviceSize": "171798691840" |
| 259 | 259 |
} |
| 260 | 260 |
} |
| 261 |
-} |
|
| 262 |
-] |
|
| 261 |
+ } |
|
| 262 |
+ ] |
|
| 263 | 263 |
|
| 264 | 264 |
# HISTORY |
| 265 | 265 |
April 2014, originally compiled by William Henry (whenry at redhat dot com) |