Browse Source

Merge pull request #11839 from brahmaroutu/template_11641

Allow go template to work properly with inspect …
Alexander Morozov 10 years ago
parent
commit
799cf056e7

+ 26 - 13
api/client/inspect.go

@@ -8,12 +8,14 @@ import (
 	"strings"
 	"text/template"
 
+	"github.com/docker/docker/api/types"
 	flag "github.com/docker/docker/pkg/mflag"
 )
 
 // CmdInspect displays low-level information on one or more containers or images.
 //
 // Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]
+
 func (cli *DockerCli) CmdInspect(args ...string) error {
 	cmd := cli.Subcmd("inspect", "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")
@@ -34,11 +36,13 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
 	indented := new(bytes.Buffer)
 	indented.WriteByte('[')
 	status := 0
+	isImage := false
 
 	for _, name := range cmd.Args() {
 		obj, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
 		if err != nil {
 			obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
+			isImage = true
 			if err != nil {
 				if strings.Contains(err.Error(), "No such") {
 					fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
@@ -57,20 +61,29 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
 				continue
 			}
 		} else {
-			var value interface{}
-
-			// Do not use `json.Unmarshal()` because unmarshal JSON into
-			// an interface value, Unmarshal stores JSON numbers in
-			// float64, which is different from `json.Indent()` does.
 			dec := json.NewDecoder(bytes.NewReader(obj))
-			dec.UseNumber()
-			if err := dec.Decode(&value); err != nil {
-				fmt.Fprintf(cli.err, "%s\n", err)
-				status = 1
-				continue
-			}
-			if err := tmpl.Execute(cli.out, value); err != nil {
-				return err
+
+			if isImage {
+				inspPtr := types.ImageInspect{}
+				if err := dec.Decode(&inspPtr); err != nil {
+					fmt.Fprintf(cli.err, "%s\n", err)
+					status = 1
+					continue
+				}
+				if err := tmpl.Execute(cli.out, inspPtr); err != nil {
+					return err
+				}
+			} else {
+				inspPtr := types.ContainerJSON{}
+				if err := dec.Decode(&inspPtr); err != nil {
+					fmt.Fprintf(cli.err, "%s\n", err)
+					status = 1
+					continue
+				}
+				if err := tmpl.Execute(cli.out, inspPtr); err != nil {
+					return err
+
+				}
 			}
 			cli.out.Write([]byte{'\n'})
 		}

+ 17 - 0
api/types/types.go

@@ -75,6 +75,23 @@ type Image struct {
 	Labels      map[string]string
 }
 
+// GET "/images/{name:.*}/json"
+type ImageInspect struct {
+	Id              string
+	Parent          string
+	Comment         string
+	Created         time.Time
+	Container       string
+	ContainerConfig *runconfig.Config
+	DockerVersion   string
+	Author          string
+	Config          *runconfig.Config
+	Architecture    string
+	Os              string
+	Size            int64
+	VirtualSize     int64
+}
+
 type LegacyImage struct {
 	ID          string `json:"Id"`
 	Repository  string

+ 1 - 1
integration-cli/docker_api_containers_test.go

@@ -644,7 +644,7 @@ func (s *DockerSuite) TestContainerApiCommit(c *check.C) {
 	if err != nil {
 		c.Fatal(err)
 	}
-	if cmd != "[/bin/sh -c touch /test]" {
+	if cmd != "{[/bin/sh -c touch /test]}" {
 		c.Fatalf("got wrong Cmd from commit: %q", cmd)
 	}
 	// sanity check, make sure the image is what we think it is

+ 15 - 14
integration-cli/docker_cli_build_test.go

@@ -2349,7 +2349,7 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
 
 func (s *DockerSuite) TestBuildCmd(c *check.C) {
 	name := "testbuildcmd"
-	expected := "[/bin/echo Hello World]"
+	expected := "{[/bin/echo Hello World]}"
 	defer deleteImages(name)
 	_, err := buildImage(name,
 		`FROM scratch
@@ -2369,7 +2369,7 @@ func (s *DockerSuite) TestBuildCmd(c *check.C) {
 
 func (s *DockerSuite) TestBuildExpose(c *check.C) {
 	name := "testbuildexpose"
-	expected := "map[2375/tcp:map[]]"
+	expected := "map[2375/tcp:{}]"
 	defer deleteImages(name)
 	_, err := buildImage(name,
 		`FROM scratch
@@ -2466,7 +2466,7 @@ func (s *DockerSuite) TestBuildExposeOrder(c *check.C) {
 
 func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
 	name := "testbuildexposeuppercaseproto"
-	expected := "map[5678/udp:map[]]"
+	expected := "map[5678/udp:{}]"
 	defer deleteImages(name)
 	_, err := buildImage(name,
 		`FROM scratch
@@ -2487,7 +2487,7 @@ func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
 func (s *DockerSuite) TestBuildExposeHostPort(c *check.C) {
 	// start building docker file with ip:hostPort:containerPort
 	name := "testbuildexpose"
-	expected := "map[5678/tcp:map[]]"
+	expected := "map[5678/tcp:{}]"
 	defer deleteImages(name)
 	_, out, err := buildImageWithOut(name,
 		`FROM scratch
@@ -2527,7 +2527,7 @@ func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
 		c.Fatal(err)
 	}
 
-	expected := "[/bin/echo]"
+	expected := "{[/bin/echo]}"
 	if res != expected {
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
 	}
@@ -2544,7 +2544,7 @@ func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
 		c.Fatal(err)
 	}
 
-	expected = "[]"
+	expected = "{[]}"
 
 	if res != expected {
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
@@ -2555,7 +2555,7 @@ func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
 func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
 	name := "testbuildentrypoint"
 	defer deleteImages(name)
-	expected := "[]"
+	expected := "{[]}"
 
 	_, err := buildImage(name,
 		`FROM busybox
@@ -2576,7 +2576,7 @@ func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
 
 func (s *DockerSuite) TestBuildEntrypoint(c *check.C) {
 	name := "testbuildentrypoint"
-	expected := "[/bin/echo]"
+	expected := "{[/bin/echo]}"
 	defer deleteImages(name)
 	_, err := buildImage(name,
 		`FROM scratch
@@ -3296,8 +3296,8 @@ func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) {
 		c.Fatal(err)
 	}
 	// Cmd must be cleaned up
-	if expected := "<no value>"; res != expected {
-		c.Fatalf("Cmd %s, expected %s", res, expected)
+	if res != "<nil>" {
+		c.Fatalf("Cmd %s, expected nil", res)
 	}
 }
 
@@ -3370,7 +3370,7 @@ func (s *DockerSuite) TestBuildInheritance(c *check.C) {
 	if err != nil {
 		c.Fatal(err)
 	}
-	if expected := "[/bin/echo]"; res != expected {
+	if expected := "{[/bin/echo]}"; res != expected {
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
 	}
 	ports2, err := inspectField(name, "Config.ExposedPorts")
@@ -4241,14 +4241,15 @@ func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
 	if err != nil {
 		c.Fatal(err)
 	}
-	if expected := "<no value>"; res != expected {
-		c.Fatalf("Cmd %s, expected %s", res, expected)
+	if res != "<nil>" {
+		c.Fatalf("Cmd %s, expected nil", res)
 	}
+
 	res, err = inspectField(name, "Config.Entrypoint")
 	if err != nil {
 		c.Fatal(err)
 	}
-	if expected := "[cat]"; res != expected {
+	if expected := "{[cat]}"; res != expected {
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
 	}
 }

+ 1 - 1
integration-cli/docker_cli_commit_test.go

@@ -251,7 +251,7 @@ func (s *DockerSuite) TestCommitChange(c *check.C) {
 	defer deleteImages(imageId)
 
 	expected := map[string]string{
-		"Config.ExposedPorts": "map[8080/tcp:map[]]",
+		"Config.ExposedPorts": "map[8080/tcp:{}]",
 		"Config.Env":          "[DEBUG=true test=1 PATH=/foo]",
 	}
 

+ 1 - 1
integration-cli/docker_cli_exec_test.go

@@ -448,7 +448,7 @@ func (s *DockerSuite) TestInspectExecID(c *check.C) {
 	if err != nil {
 		c.Fatalf("failed to inspect container: %s, %v", out, err)
 	}
-	if out != "<no value>" {
+	if out != "[]" {
 		c.Fatalf("ExecIDs should be empty, got: %s", out)
 	}
 

+ 57 - 0
integration-cli/docker_cli_inspect_test.go

@@ -1,7 +1,9 @@
 package main
 
 import (
+	"fmt"
 	"os/exec"
+	"strconv"
 	"strings"
 
 	"github.com/go-check/check"
@@ -41,3 +43,58 @@ func (s *DockerSuite) TestInspectInt64(c *check.C) {
 		c.Fatalf("inspect got wrong value, got: %q, expected: 314572800", inspectOut)
 	}
 }
+
+func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
+	imageTest := "emptyfs"
+	imagesCmd := exec.Command(dockerBinary, "inspect", "--format='{{.Size}}'", imageTest)
+	out, exitCode, err := runCommandWithOutput(imagesCmd)
+	if exitCode != 0 || err != nil {
+		c.Fatalf("failed to inspect image: %s, %v", out, err)
+	}
+	size, err := strconv.Atoi(strings.TrimSuffix(out, "\n"))
+	if err != nil {
+		c.Fatalf("failed to inspect size of the image: %s, %v", out, err)
+	}
+
+	//now see if the size turns out to be the same
+	formatStr := fmt.Sprintf("--format='{{eq .Size %d}}'", size)
+	imagesCmd = exec.Command(dockerBinary, "inspect", formatStr, imageTest)
+	out, exitCode, err = runCommandWithOutput(imagesCmd)
+	if exitCode != 0 || err != nil {
+		c.Fatalf("failed to inspect image: %s, %v", out, err)
+	}
+	if result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n")); err != nil || !result {
+		c.Fatalf("Expected size: %d for image: %s but received size: %s", size, imageTest, strings.TrimSuffix(out, "\n"))
+	}
+}
+
+func (s *DockerSuite) TestInspectContainerFilterInt(c *check.C) {
+	runCmd := exec.Command("bash", "-c", `echo "blahblah" | docker run -i -a stdin busybox cat`)
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+
+	id := strings.TrimSpace(out)
+
+	runCmd = exec.Command(dockerBinary, "inspect", "--format='{{.State.ExitCode}}'", id)
+	out, _, err = runCommandWithOutput(runCmd)
+	if err != nil {
+		c.Fatalf("failed to inspect container: %s, %v", out, err)
+	}
+	exitCode, err := strconv.Atoi(strings.TrimSuffix(out, "\n"))
+	if err != nil {
+		c.Fatalf("failed to inspect exitcode of the container: %s, %v", out, err)
+	}
+
+	//now get the exit code to verify
+	formatStr := fmt.Sprintf("--format='{{eq .State.ExitCode %d}}'", exitCode)
+	runCmd = exec.Command(dockerBinary, "inspect", formatStr, id)
+	out, _, err = runCommandWithOutput(runCmd)
+	if err != nil {
+		c.Fatalf("failed to inspect container: %s, %v", out, err)
+	}
+	if result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n")); err != nil || !result {
+		c.Fatalf("Expected exitcode: %d for container: %s", exitCode, id)
+	}
+}

+ 2 - 2
integration-cli/docker_cli_run_test.go

@@ -2441,7 +2441,7 @@ func (s *DockerSuite) TestRunVolumesCleanPaths(c *check.C) {
 	if err != nil {
 		c.Fatal(err)
 	}
-	if out != "<no value>" {
+	if out != "" {
 		c.Fatalf("Found unexpected volume entry for '/foo/' in volumes\n%q", out)
 	}
 
@@ -2457,7 +2457,7 @@ func (s *DockerSuite) TestRunVolumesCleanPaths(c *check.C) {
 	if err != nil {
 		c.Fatal(err)
 	}
-	if out != "<no value>" {
+	if out != "" {
 		c.Fatalf("Found unexpected volume entry for '/bar/' in volumes\n%q", out)
 	}
 	out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar")