moby--moby/integration-cli/daemon/daemon.go

209 lines
6.3 KiB
Go
Raw Normal View History

package daemon // import "github.com/docker/docker/integration-cli/daemon"
import (
"fmt"
"os/exec"
"strings"
"time"
"github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/internal/test/daemon"
"github.com/go-check/check"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/icmd"
"github.com/pkg/errors"
)
type testingT interface {
assert.TestingT
logT
Fatalf(string, ...interface{})
}
type logT interface {
Logf(string, ...interface{})
}
// Daemon represents a Docker daemon for the testing framework.
type Daemon struct {
*daemon.Daemon
dockerBinary string
}
// Config holds docker daemon integration configuration
type Config struct {
Experimental bool
}
// New returns a Daemon instance to be used for testing.
[EXPERIMENTAL] Integration Test on Swarm This commit adds contrib/integration-cli-on-swarm/integration-cli-on-swarm.sh, which enables IT to be running in parallel, using Swarm-mode and Funker. Please refer to contrib/integration-cli-on-swarm/README.md The test takes almost 5 to 6 minutes, with 10 n1-standard-4 GCE instances. $ ./contrib/integration-cli-on-swarm/integration-cli-on-swarm.sh --push-worker-image example.gcr.io/foo/bar --replicas 30 --shuffle 2016/12/29 08:32:15 Loaded 1618 tests (30 chunks) 2016/12/29 08:32:15 Executing 30 chunks in parallel, against "integration-cli-worker" 2016/12/29 08:32:15 Executing chunk 0 (contains 54 test filters) .. 2016/12/29 08:34:34 Finished chunk 28 [1/30] with 54 test filters in 2m19.098068003s, code=0. 2016/12/29 08:34:38 Finished chunk 12 [2/30] with 54 test filters in 2m23.088569511s, code=0. 2016/12/29 08:34:48 Finished chunk 10 [3/30] with 54 test filters in 2m33.880679079s, code=0. 2016/12/29 08:34:54 Finished chunk 20 [4/30] with 54 test filters in 2m39.973747028s, code=0. 2016/12/29 08:35:11 Finished chunk 18 [5/30] with 54 test filters in 2m56.28384361s, code=0. 2016/12/29 08:35:11 Finished chunk 29 [6/30] with 52 test filters in 2m56.54047088s, code=0. 2016/12/29 08:35:15 Finished chunk 1 [7/30] with 54 test filters in 3m0.285044426s, code=0. 2016/12/29 08:35:22 Finished chunk 6 [8/30] with 54 test filters in 3m7.211775338s, code=0. 2016/12/29 08:35:24 Finished chunk 25 [9/30] with 54 test filters in 3m9.938413009s, code=0. 2016/12/29 08:35:30 Finished chunk 27 [10/30] with 54 test filters in 3m15.219834368s, code=0. 2016/12/29 08:35:36 Finished chunk 9 [11/30] with 54 test filters in 3m21.615434162s, code=0. 2016/12/29 08:35:41 Finished chunk 13 [12/30] with 54 test filters in 3m26.576907401s, code=0. 2016/12/29 08:35:45 Finished chunk 17 [13/30] with 54 test filters in 3m30.290752537s, code=0. 2016/12/29 08:35:53 Finished chunk 2 [14/30] with 54 test filters in 3m38.148423321s, code=0. 2016/12/29 08:35:55 Finished chunk 24 [15/30] with 54 test filters in 3m40.09669137s, code=0. 2016/12/29 08:35:57 Finished chunk 8 [16/30] with 54 test filters in 3m42.299945108s, code=0. 2016/12/29 08:35:57 Finished chunk 22 [17/30] with 54 test filters in 3m42.946558809s, code=0. 2016/12/29 08:35:59 Finished chunk 23 [18/30] with 54 test filters in 3m44.232557165s, code=0. 2016/12/29 08:36:02 Finished chunk 3 [19/30] with 54 test filters in 3m47.112051358s, code=0. 2016/12/29 08:36:11 Finished chunk 15 [20/30] with 54 test filters in 3m56.340656645s, code=0. 2016/12/29 08:36:11 Finished chunk 11 [21/30] with 54 test filters in 3m56.882401231s, code=0. 2016/12/29 08:36:22 Finished chunk 19 [22/30] with 54 test filters in 4m7.551093516s, code=0. 2016/12/29 08:36:23 Finished chunk 21 [23/30] with 54 test filters in 4m8.221093446s, code=0. 2016/12/29 08:36:25 Finished chunk 16 [24/30] with 54 test filters in 4m10.450451705s, code=0. 2016/12/29 08:36:27 Finished chunk 5 [25/30] with 54 test filters in 4m12.162272692s, code=0. 2016/12/29 08:36:28 Finished chunk 14 [26/30] with 54 test filters in 4m13.977801031s, code=0. 2016/12/29 08:36:29 Finished chunk 0 [27/30] with 54 test filters in 4m14.34086812s, code=0. 2016/12/29 08:36:49 Finished chunk 26 [28/30] with 54 test filters in 4m34.437085539s, code=0. 2016/12/29 08:37:14 Finished chunk 7 [29/30] with 54 test filters in 4m59.22902721s, code=0. 2016/12/29 08:37:20 Finished chunk 4 [30/30] with 54 test filters in 5m5.103469214s, code=0. 2016/12/29 08:37:20 Executed 30 chunks in 5m5.104379119s. PASS: 30, FAIL: 0. Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
2016-12-07 07:16:48 +00:00
// This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST.
// The daemon will not automatically start.
func New(t testingT, dockerBinary string, dockerdBinary string, config Config) *Daemon {
ops := []func(*daemon.Daemon){
daemon.WithDockerdBinary(dockerdBinary),
}
if config.Experimental {
ops = append(ops, daemon.WithExperimental)
}
d := daemon.New(t, ops...)
return &Daemon{
Daemon: d,
dockerBinary: dockerBinary,
}
}
// Cmd executes a docker CLI command against this daemon.
// Example: d.Cmd("version") will run docker -H unix://path/to/unix.sock version
func (d *Daemon) Cmd(args ...string) (string, error) {
result := icmd.RunCmd(d.Command(args...))
return result.Combined(), result.Error
}
// Command creates a docker CLI command against this daemon, to be executed later.
// Example: d.Command("version") creates a command to run "docker -H unix://path/to/unix.sock version"
func (d *Daemon) Command(args ...string) icmd.Cmd {
return icmd.Command(d.dockerBinary, d.PrependHostArg(args)...)
}
// PrependHostArg prepend the specified arguments by the daemon host flags
func (d *Daemon) PrependHostArg(args []string) []string {
for _, arg := range args {
if arg == "--host" || arg == "-H" {
return args
}
}
return append([]string{"--host", d.Sock()}, args...)
}
// GetIDByName returns the ID of an object (container, volume, …) given its name
func (d *Daemon) GetIDByName(name string) (string, error) {
return d.inspectFieldWithError(name, "Id")
}
// ActiveContainers returns the list of ids of the currently running containers
func (d *Daemon) ActiveContainers() (ids []string) {
// FIXME(vdemeester) shouldn't ignore the error
out, _ := d.Cmd("ps", "-q")
for _, id := range strings.Split(out, "\n") {
if id = strings.TrimSpace(id); id != "" {
ids = append(ids, id)
}
}
return
}
// InspectField returns the field filter by 'filter'
func (d *Daemon) InspectField(name, filter string) (string, error) {
return d.inspectFilter(name, filter)
}
func (d *Daemon) inspectFilter(name, filter string) (string, error) {
format := fmt.Sprintf("{{%s}}", filter)
out, err := d.Cmd("inspect", "-f", format, name)
if err != nil {
return "", errors.Errorf("failed to inspect %s: %s", name, out)
}
return strings.TrimSpace(out), nil
}
func (d *Daemon) inspectFieldWithError(name, field string) (string, error) {
return d.inspectFilter(name, fmt.Sprintf(".%s", field))
}
// FindContainerIP returns the ip of the specified container
func (d *Daemon) FindContainerIP(id string) (string, error) {
out, err := d.Cmd("inspect", "--format='{{ .NetworkSettings.Networks.bridge.IPAddress }}'", id)
if err != nil {
return "", err
}
return strings.Trim(out, " \r\n'"), nil
}
// BuildImageWithOut builds an image with the specified dockerfile and options and returns the output
func (d *Daemon) BuildImageWithOut(name, dockerfile string, useCache bool, buildFlags ...string) (string, int, error) {
buildCmd := BuildImageCmdWithHost(d.dockerBinary, name, dockerfile, d.Sock(), useCache, buildFlags...)
result := icmd.RunCmd(icmd.Cmd{
Command: buildCmd.Args,
Env: buildCmd.Env,
Dir: buildCmd.Dir,
Stdin: buildCmd.Stdin,
Stdout: buildCmd.Stdout,
})
return result.Combined(), result.ExitCode, result.Error
}
// CheckActiveContainerCount returns the number of active containers
// FIXME(vdemeester) should re-use ActivateContainers in some way
func (d *Daemon) CheckActiveContainerCount(c *check.C) (interface{}, check.CommentInterface) {
out, err := d.Cmd("ps", "-q")
c.Assert(err, checker.IsNil)
if len(strings.TrimSpace(out)) == 0 {
return 0, nil
}
return len(strings.Split(strings.TrimSpace(out), "\n")), check.Commentf("output: %q", string(out))
}
// WaitRun waits for a container to be running for 10s
func (d *Daemon) WaitRun(contID string) error {
args := []string{"--host", d.Sock()}
return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
}
// WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
// Deprecated: use cli.WaitCmd instead
func WaitInspectWithArgs(dockerBinary, name, expr, expected string, timeout time.Duration, arg ...string) error {
after := time.After(timeout)
args := append(arg, "inspect", "-f", expr, name)
for {
result := icmd.RunCommand(dockerBinary, args...)
if result.Error != nil {
if !strings.Contains(strings.ToLower(result.Stderr()), "no such") {
return errors.Errorf("error executing docker inspect: %v\n%s",
result.Stderr(), result.Stdout())
}
select {
case <-after:
return result.Error
default:
time.Sleep(10 * time.Millisecond)
continue
}
}
out := strings.TrimSpace(result.Stdout())
if out == expected {
break
}
select {
case <-after:
return errors.Errorf("condition \"%q == %q\" not true in time (%v)", out, expected, timeout)
default:
}
time.Sleep(100 * time.Millisecond)
}
return nil
}
// BuildImageCmdWithHost create a build command with the specified arguments.
// Deprecated
// FIXME(vdemeester) move this away
func BuildImageCmdWithHost(dockerBinary, name, dockerfile, host string, useCache bool, buildFlags ...string) *exec.Cmd {
args := []string{}
if host != "" {
args = append(args, "--host", host)
}
args = append(args, "build", "-t", name)
if !useCache {
args = append(args, "--no-cache")
}
args = append(args, buildFlags...)
args = append(args, "-")
buildCmd := exec.Command(dockerBinary, args...)
buildCmd.Stdin = strings.NewReader(dockerfile)
return buildCmd
}