inspect.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package client
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "strings"
  8. "text/template"
  9. "github.com/docker/docker/api/types"
  10. flag "github.com/docker/docker/pkg/mflag"
  11. )
  12. // CmdInspect displays low-level information on one or more containers or images.
  13. //
  14. // Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]
  15. func (cli *DockerCli) CmdInspect(args ...string) error {
  16. cmd := cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, "Return low-level information on a container or image", true)
  17. tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
  18. inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
  19. cmd.Require(flag.Min, 1)
  20. cmd.ParseFlags(args, true)
  21. var tmpl *template.Template
  22. var err error
  23. var obj []byte
  24. if *tmplStr != "" {
  25. if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
  26. return StatusError{StatusCode: 64,
  27. Status: "Template parsing error: " + err.Error()}
  28. }
  29. }
  30. if *inspectType != "" && *inspectType != "container" && *inspectType != "image" {
  31. return fmt.Errorf("%q is not a valid value for --type", *inspectType)
  32. }
  33. indented := new(bytes.Buffer)
  34. indented.WriteString("[\n")
  35. status := 0
  36. isImage := false
  37. for _, name := range cmd.Args() {
  38. if *inspectType == "" || *inspectType == "container" {
  39. obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
  40. if err != nil && *inspectType == "container" {
  41. if strings.Contains(err.Error(), "No such") {
  42. fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)
  43. } else {
  44. fmt.Fprintf(cli.err, "%s", err)
  45. }
  46. status = 1
  47. continue
  48. }
  49. }
  50. if obj == nil && (*inspectType == "" || *inspectType == "image") {
  51. obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
  52. isImage = true
  53. if err != nil {
  54. if strings.Contains(err.Error(), "No such") {
  55. if *inspectType == "" {
  56. fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
  57. } else {
  58. fmt.Fprintf(cli.err, "Error: No such image: %s\n", name)
  59. }
  60. } else {
  61. fmt.Fprintf(cli.err, "%s", err)
  62. }
  63. status = 1
  64. continue
  65. }
  66. }
  67. if tmpl == nil {
  68. if err := json.Indent(indented, obj, "", " "); err != nil {
  69. fmt.Fprintf(cli.err, "%s\n", err)
  70. status = 1
  71. continue
  72. }
  73. } else {
  74. rdr := bytes.NewReader(obj)
  75. dec := json.NewDecoder(rdr)
  76. if isImage {
  77. inspPtr := types.ImageInspect{}
  78. if err := dec.Decode(&inspPtr); err != nil {
  79. fmt.Fprintf(cli.err, "%s\n", err)
  80. status = 1
  81. continue
  82. }
  83. if err := tmpl.Execute(cli.out, inspPtr); err != nil {
  84. rdr.Seek(0, 0)
  85. var raw interface{}
  86. if err := dec.Decode(&raw); err != nil {
  87. return err
  88. }
  89. if err = tmpl.Execute(cli.out, raw); err != nil {
  90. return err
  91. }
  92. }
  93. } else {
  94. inspPtr := types.ContainerJSON{}
  95. if err := dec.Decode(&inspPtr); err != nil {
  96. fmt.Fprintf(cli.err, "%s\n", err)
  97. status = 1
  98. continue
  99. }
  100. if err := tmpl.Execute(cli.out, inspPtr); err != nil {
  101. rdr.Seek(0, 0)
  102. var raw interface{}
  103. if err := dec.Decode(&raw); err != nil {
  104. return err
  105. }
  106. if err = tmpl.Execute(cli.out, raw); err != nil {
  107. return err
  108. }
  109. }
  110. }
  111. cli.out.Write([]byte{'\n'})
  112. }
  113. indented.WriteString(",")
  114. }
  115. if indented.Len() > 1 {
  116. // Remove trailing ','
  117. indented.Truncate(indented.Len() - 1)
  118. }
  119. indented.WriteString("]\n")
  120. if tmpl == nil {
  121. // Note that we will always write "[]" when "-f" isn't specified,
  122. // to make sure the output would always be array, see
  123. // https://github.com/docker/docker/pull/9500#issuecomment-65846734
  124. if _, err := io.Copy(cli.out, indented); err != nil {
  125. return err
  126. }
  127. }
  128. if status != 0 {
  129. return StatusError{StatusCode: status}
  130. }
  131. return nil
  132. }