inspect.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package system
  2. import (
  3. "fmt"
  4. "golang.org/x/net/context"
  5. "github.com/docker/docker/cli"
  6. "github.com/docker/docker/cli/command"
  7. "github.com/docker/docker/cli/command/inspect"
  8. apiclient "github.com/docker/docker/client"
  9. "github.com/spf13/cobra"
  10. )
  11. type inspectOptions struct {
  12. format string
  13. inspectType string
  14. size bool
  15. ids []string
  16. }
  17. // NewInspectCommand creates a new cobra.Command for `docker inspect`
  18. func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
  19. var opts inspectOptions
  20. cmd := &cobra.Command{
  21. Use: "inspect [OPTIONS] NAME|ID [NAME|ID...]",
  22. Short: "Return low-level information on Docker objects",
  23. Args: cli.RequiresMinArgs(1),
  24. RunE: func(cmd *cobra.Command, args []string) error {
  25. opts.ids = args
  26. return runInspect(dockerCli, opts)
  27. },
  28. }
  29. flags := cmd.Flags()
  30. flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
  31. flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type")
  32. flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")
  33. return cmd
  34. }
  35. func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
  36. var elementSearcher inspect.GetRefFunc
  37. switch opts.inspectType {
  38. case "", "container", "image", "node", "network", "service", "volume", "task", "plugin":
  39. elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
  40. default:
  41. return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
  42. }
  43. return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
  44. }
  45. func inspectContainers(ctx context.Context, dockerCli *command.DockerCli, getSize bool) inspect.GetRefFunc {
  46. return func(ref string) (interface{}, []byte, error) {
  47. return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize)
  48. }
  49. }
  50. func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  51. return func(ref string) (interface{}, []byte, error) {
  52. return dockerCli.Client().ImageInspectWithRaw(ctx, ref)
  53. }
  54. }
  55. func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  56. return func(ref string) (interface{}, []byte, error) {
  57. return dockerCli.Client().NetworkInspectWithRaw(ctx, ref)
  58. }
  59. }
  60. func inspectNode(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  61. return func(ref string) (interface{}, []byte, error) {
  62. return dockerCli.Client().NodeInspectWithRaw(ctx, ref)
  63. }
  64. }
  65. func inspectService(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  66. return func(ref string) (interface{}, []byte, error) {
  67. return dockerCli.Client().ServiceInspectWithRaw(ctx, ref)
  68. }
  69. }
  70. func inspectTasks(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  71. return func(ref string) (interface{}, []byte, error) {
  72. return dockerCli.Client().TaskInspectWithRaw(ctx, ref)
  73. }
  74. }
  75. func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  76. return func(ref string) (interface{}, []byte, error) {
  77. return dockerCli.Client().VolumeInspectWithRaw(ctx, ref)
  78. }
  79. }
  80. func inspectPlugin(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  81. return func(ref string) (interface{}, []byte, error) {
  82. return dockerCli.Client().PluginInspectWithRaw(ctx, ref)
  83. }
  84. }
  85. func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
  86. var inspectAutodetect = []struct {
  87. objectType string
  88. isSizeSupported bool
  89. isSwarmObject bool
  90. objectInspector func(string) (interface{}, []byte, error)
  91. }{
  92. {
  93. objectType: "container",
  94. isSizeSupported: true,
  95. objectInspector: inspectContainers(ctx, dockerCli, getSize),
  96. },
  97. {
  98. objectType: "image",
  99. objectInspector: inspectImages(ctx, dockerCli),
  100. },
  101. {
  102. objectType: "network",
  103. objectInspector: inspectNetwork(ctx, dockerCli),
  104. },
  105. {
  106. objectType: "volume",
  107. objectInspector: inspectVolume(ctx, dockerCli),
  108. },
  109. {
  110. objectType: "service",
  111. isSwarmObject: true,
  112. objectInspector: inspectService(ctx, dockerCli),
  113. },
  114. {
  115. objectType: "task",
  116. isSwarmObject: true,
  117. objectInspector: inspectTasks(ctx, dockerCli),
  118. },
  119. {
  120. objectType: "node",
  121. isSwarmObject: true,
  122. objectInspector: inspectNode(ctx, dockerCli),
  123. },
  124. {
  125. objectType: "plugin",
  126. objectInspector: inspectPlugin(ctx, dockerCli),
  127. },
  128. }
  129. // isSwarmManager does an Info API call to verify that the daemon is
  130. // a swarm manager.
  131. isSwarmManager := func() bool {
  132. info, err := dockerCli.Client().Info(ctx)
  133. if err != nil {
  134. fmt.Fprintln(dockerCli.Err(), err)
  135. return false
  136. }
  137. return info.Swarm.ControlAvailable
  138. }
  139. return func(ref string) (interface{}, []byte, error) {
  140. const (
  141. swarmSupportUnknown = iota
  142. swarmSupported
  143. swarmUnsupported
  144. )
  145. isSwarmSupported := swarmSupportUnknown
  146. for _, inspectData := range inspectAutodetect {
  147. if typeConstraint != "" && inspectData.objectType != typeConstraint {
  148. continue
  149. }
  150. if typeConstraint == "" && inspectData.isSwarmObject {
  151. if isSwarmSupported == swarmSupportUnknown {
  152. if isSwarmManager() {
  153. isSwarmSupported = swarmSupported
  154. } else {
  155. isSwarmSupported = swarmUnsupported
  156. }
  157. }
  158. if isSwarmSupported == swarmUnsupported {
  159. continue
  160. }
  161. }
  162. v, raw, err := inspectData.objectInspector(ref)
  163. if err != nil {
  164. if typeConstraint == "" && apiclient.IsErrNotFound(err) {
  165. continue
  166. }
  167. return v, raw, err
  168. }
  169. if getSize && !inspectData.isSizeSupported {
  170. fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.objectType)
  171. }
  172. return v, raw, err
  173. }
  174. return nil, nil, fmt.Errorf("Error: No such object: %s", ref)
  175. }
  176. }