inspect.go 6.2 KB

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