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