daemon.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package daemon // import "github.com/docker/docker/integration-cli/daemon"
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "testing"
  7. "time"
  8. "github.com/docker/docker/testutil/daemon"
  9. "github.com/pkg/errors"
  10. "gotest.tools/v3/assert"
  11. "gotest.tools/v3/icmd"
  12. )
  13. // Daemon represents a Docker daemon for the testing framework.
  14. type Daemon struct {
  15. *daemon.Daemon
  16. dockerBinary string
  17. }
  18. // New returns a Daemon instance to be used for testing.
  19. // This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST.
  20. // The daemon will not automatically start.
  21. func New(t testing.TB, dockerBinary string, dockerdBinary string, ops ...daemon.Option) *Daemon {
  22. t.Helper()
  23. ops = append(ops, daemon.WithDockerdBinary(dockerdBinary))
  24. d := daemon.New(t, ops...)
  25. return &Daemon{
  26. Daemon: d,
  27. dockerBinary: dockerBinary,
  28. }
  29. }
  30. // Cmd executes a docker CLI command against this daemon.
  31. // Example: d.Cmd("version") will run docker -H unix://path/to/unix.sock version
  32. func (d *Daemon) Cmd(args ...string) (string, error) {
  33. result := icmd.RunCmd(d.Command(args...))
  34. return result.Combined(), result.Error
  35. }
  36. // Command creates a docker CLI command against this daemon, to be executed later.
  37. // Example: d.Command("version") creates a command to run "docker -H unix://path/to/unix.sock version"
  38. func (d *Daemon) Command(args ...string) icmd.Cmd {
  39. return icmd.Command(d.dockerBinary, d.PrependHostArg(args)...)
  40. }
  41. // PrependHostArg prepend the specified arguments by the daemon host flags
  42. func (d *Daemon) PrependHostArg(args []string) []string {
  43. for _, arg := range args {
  44. if arg == "--host" || arg == "-H" {
  45. return args
  46. }
  47. }
  48. return append([]string{"--host", d.Sock()}, args...)
  49. }
  50. // GetIDByName returns the ID of an object (container, volume, …) given its name
  51. func (d *Daemon) GetIDByName(name string) (string, error) {
  52. return d.inspectFieldWithError(name, "Id")
  53. }
  54. // InspectField returns the field filter by 'filter'
  55. func (d *Daemon) InspectField(name, filter string) (string, error) {
  56. return d.inspectFilter(name, filter)
  57. }
  58. func (d *Daemon) inspectFilter(name, filter string) (string, error) {
  59. format := fmt.Sprintf("{{%s}}", filter)
  60. out, err := d.Cmd("inspect", "-f", format, name)
  61. if err != nil {
  62. return "", errors.Errorf("failed to inspect %s: %s", name, out)
  63. }
  64. return strings.TrimSpace(out), nil
  65. }
  66. func (d *Daemon) inspectFieldWithError(name, field string) (string, error) {
  67. return d.inspectFilter(name, "."+field)
  68. }
  69. // CheckActiveContainerCount returns the number of active containers
  70. // FIXME(vdemeester) should re-use ActivateContainers in some way
  71. func (d *Daemon) CheckActiveContainerCount(ctx context.Context) func(t *testing.T) (interface{}, string) {
  72. return func(t *testing.T) (interface{}, string) {
  73. t.Helper()
  74. out, err := d.Cmd("ps", "-q")
  75. assert.NilError(t, err)
  76. if len(strings.TrimSpace(out)) == 0 {
  77. return 0, ""
  78. }
  79. return len(strings.Split(strings.TrimSpace(out), "\n")), fmt.Sprintf("output: %q", out)
  80. }
  81. }
  82. // WaitRun waits for a container to be running for 10s
  83. func (d *Daemon) WaitRun(contID string) error {
  84. args := []string{"--host", d.Sock()}
  85. return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
  86. }
  87. // WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
  88. // Deprecated: use cli.WaitCmd instead
  89. func WaitInspectWithArgs(dockerBinary, name, expr, expected string, timeout time.Duration, arg ...string) error {
  90. after := time.After(timeout)
  91. args := append(arg, "inspect", "-f", expr, name)
  92. for {
  93. result := icmd.RunCommand(dockerBinary, args...)
  94. if result.Error != nil {
  95. if !strings.Contains(strings.ToLower(result.Stderr()), "no such") {
  96. return errors.Errorf("error executing docker inspect: %v\n%s",
  97. result.Stderr(), result.Stdout())
  98. }
  99. select {
  100. case <-after:
  101. return result.Error
  102. default:
  103. time.Sleep(10 * time.Millisecond)
  104. continue
  105. }
  106. }
  107. out := strings.TrimSpace(result.Stdout())
  108. if out == expected {
  109. break
  110. }
  111. select {
  112. case <-after:
  113. return errors.Errorf("condition \"%q == %q\" not true in time (%v)", out, expected, timeout)
  114. default:
  115. }
  116. time.Sleep(100 * time.Millisecond)
  117. }
  118. return nil
  119. }