inspect.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package system
  2. import (
  3. "fmt"
  4. "strings"
  5. "golang.org/x/net/context"
  6. "github.com/docker/docker/api/client"
  7. "github.com/docker/docker/api/client/inspect"
  8. "github.com/docker/docker/cli"
  9. apiclient "github.com/docker/engine-api/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 *client.DockerCli) *cobra.Command {
  20. var opts inspectOptions
  21. cmd := &cobra.Command{
  22. Use: "inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...]",
  23. Short: "Return low-level information on a container, image or task",
  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, (e.g image, container or task)")
  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 *client.DockerCli, opts inspectOptions) error {
  37. ctx := context.Background()
  38. client := dockerCli.Client()
  39. var getRefFunc inspect.GetRefFunc
  40. switch opts.inspectType {
  41. case "container":
  42. getRefFunc = func(ref string) (interface{}, []byte, error) {
  43. return client.ContainerInspectWithRaw(ctx, ref, opts.size)
  44. }
  45. case "image":
  46. getRefFunc = func(ref string) (interface{}, []byte, error) {
  47. return client.ImageInspectWithRaw(ctx, ref)
  48. }
  49. case "task":
  50. if opts.size {
  51. fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
  52. }
  53. getRefFunc = func(ref string) (interface{}, []byte, error) {
  54. return client.TaskInspectWithRaw(ctx, ref)
  55. }
  56. case "":
  57. getRefFunc = inspectAll(ctx, dockerCli, opts.size)
  58. default:
  59. return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
  60. }
  61. return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, getRefFunc)
  62. }
  63. func inspectAll(ctx context.Context, dockerCli *client.DockerCli, getSize bool) inspect.GetRefFunc {
  64. client := dockerCli.Client()
  65. return func(ref string) (interface{}, []byte, error) {
  66. c, rawContainer, err := client.ContainerInspectWithRaw(ctx, ref, getSize)
  67. if err == nil || !apiclient.IsErrNotFound(err) {
  68. return c, rawContainer, err
  69. }
  70. // Search for image with that id if a container doesn't exist.
  71. i, rawImage, err := client.ImageInspectWithRaw(ctx, ref)
  72. if err == nil || !apiclient.IsErrNotFound(err) {
  73. return i, rawImage, err
  74. }
  75. // Search for task with that id if an image doesn't exist.
  76. t, rawTask, err := client.TaskInspectWithRaw(ctx, ref)
  77. if err == nil || !(apiclient.IsErrNotFound(err) || isErrorNoSwarmMode(err)) {
  78. if getSize {
  79. fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
  80. }
  81. return t, rawTask, err
  82. }
  83. return nil, nil, fmt.Errorf("Error: No such container, image or task: %s", ref)
  84. }
  85. }
  86. func isErrorNoSwarmMode(err error) bool {
  87. return strings.Contains(err.Error(), "This node is not a swarm manager")
  88. }