inspect.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package system
  2. import (
  3. "fmt"
  4. "strings"
  5. "golang.org/x/net/context"
  6. "github.com/docker/docker/cli"
  7. "github.com/docker/docker/cli/command"
  8. "github.com/docker/docker/cli/command/inspect"
  9. apiclient "github.com/docker/docker/client"
  10. "github.com/spf13/cobra"
  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: strings.Join([]string{
  24. "Return low-level information on Docker object(s) (e.g. container, image, volume,",
  25. "\nnetwork, node, service, or task) identified by name or ID",
  26. }, ""),
  27. Args: cli.RequiresMinArgs(1),
  28. RunE: func(cmd *cobra.Command, args []string) error {
  29. opts.ids = args
  30. return runInspect(dockerCli, opts)
  31. },
  32. }
  33. flags := cmd.Flags()
  34. flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
  35. flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type")
  36. flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")
  37. return cmd
  38. }
  39. func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
  40. var elementSearcher inspect.GetRefFunc
  41. switch opts.inspectType {
  42. case "", "container", "image", "node", "network", "service", "volume", "task":
  43. elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
  44. default:
  45. return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
  46. }
  47. return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
  48. }
  49. func inspectContainers(ctx context.Context, dockerCli *command.DockerCli, getSize bool) inspect.GetRefFunc {
  50. return func(ref string) (interface{}, []byte, error) {
  51. return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize)
  52. }
  53. }
  54. func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  55. return func(ref string) (interface{}, []byte, error) {
  56. return dockerCli.Client().ImageInspectWithRaw(ctx, ref)
  57. }
  58. }
  59. func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  60. return func(ref string) (interface{}, []byte, error) {
  61. return dockerCli.Client().NetworkInspectWithRaw(ctx, ref)
  62. }
  63. }
  64. func inspectNode(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  65. return func(ref string) (interface{}, []byte, error) {
  66. return dockerCli.Client().NodeInspectWithRaw(ctx, ref)
  67. }
  68. }
  69. func inspectService(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  70. return func(ref string) (interface{}, []byte, error) {
  71. return dockerCli.Client().ServiceInspectWithRaw(ctx, ref)
  72. }
  73. }
  74. func inspectTasks(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  75. return func(ref string) (interface{}, []byte, error) {
  76. return dockerCli.Client().TaskInspectWithRaw(ctx, ref)
  77. }
  78. }
  79. func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
  80. return func(ref string) (interface{}, []byte, error) {
  81. return dockerCli.Client().VolumeInspectWithRaw(ctx, ref)
  82. }
  83. }
  84. func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
  85. var inspectAutodetect = []struct {
  86. ObjectType string
  87. IsSizeSupported bool
  88. ObjectInspector func(string) (interface{}, []byte, error)
  89. }{
  90. {"container", true, inspectContainers(ctx, dockerCli, getSize)},
  91. {"image", false, inspectImages(ctx, dockerCli)},
  92. {"network", false, inspectNetwork(ctx, dockerCli)},
  93. {"volume", false, inspectVolume(ctx, dockerCli)},
  94. {"service", false, inspectService(ctx, dockerCli)},
  95. {"task", false, inspectTasks(ctx, dockerCli)},
  96. {"node", false, inspectNode(ctx, dockerCli)},
  97. }
  98. isErrNotSwarmManager := func(err error) bool {
  99. return strings.Contains(err.Error(), "This node is not a swarm manager")
  100. }
  101. return func(ref string) (interface{}, []byte, error) {
  102. for _, inspectData := range inspectAutodetect {
  103. if typeConstraint != "" && inspectData.ObjectType != typeConstraint {
  104. continue
  105. }
  106. v, raw, err := inspectData.ObjectInspector(ref)
  107. if err != nil {
  108. if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSwarmManager(err)) {
  109. continue
  110. }
  111. return v, raw, err
  112. }
  113. if getSize && !inspectData.IsSizeSupported {
  114. fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.ObjectType)
  115. }
  116. return v, raw, err
  117. }
  118. return nil, nil, fmt.Errorf("Error: No such object: %s", ref)
  119. }
  120. }