2018-02-05 16:05:59 -05:00
|
|
|
package daemon // import "github.com/docker/docker/integration-cli/daemon"
|
2016-03-04 03:29:24 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2019-09-09 17:06:12 -04:00
|
|
|
"testing"
|
2016-03-04 03:29:24 -05:00
|
|
|
"time"
|
|
|
|
|
2019-08-29 16:52:40 -04:00
|
|
|
"github.com/docker/docker/testutil/daemon"
|
2016-12-09 04:18:02 -05:00
|
|
|
"github.com/pkg/errors"
|
2020-02-07 08:39:24 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
"gotest.tools/v3/icmd"
|
2016-03-04 03:29:24 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// Daemon represents a Docker daemon for the testing framework.
|
|
|
|
type Daemon struct {
|
2018-04-10 10:29:48 -04:00
|
|
|
*daemon.Daemon
|
|
|
|
dockerBinary string
|
2016-12-09 04:17:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 02:16:48 -05:00
|
|
|
// This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST.
|
2016-03-04 03:29:24 -05:00
|
|
|
// The daemon will not automatically start.
|
2019-09-23 07:54:51 -04:00
|
|
|
func New(t testing.TB, dockerBinary string, dockerdBinary string, ops ...daemon.Option) *Daemon {
|
2019-10-21 06:40:22 -04:00
|
|
|
t.Helper()
|
2018-04-11 06:10:17 -04:00
|
|
|
ops = append(ops, daemon.WithDockerdBinary(dockerdBinary))
|
2018-04-10 10:29:48 -04:00
|
|
|
d := daemon.New(t, ops...)
|
2016-03-04 03:29:24 -05:00
|
|
|
return &Daemon{
|
2018-04-10 10:29:48 -04:00
|
|
|
Daemon: d,
|
|
|
|
dockerBinary: dockerBinary,
|
2016-03-04 03:29:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 10:55:51 -05:00
|
|
|
// Cmd executes a docker CLI command against this daemon.
|
2016-03-04 03:29:24 -05:00
|
|
|
// Example: d.Cmd("version") will run docker -H unix://path/to/unix.sock version
|
2016-07-22 12:14:05 -04:00
|
|
|
func (d *Daemon) Cmd(args ...string) (string, error) {
|
2017-01-16 10:39:12 -05:00
|
|
|
result := icmd.RunCmd(d.Command(args...))
|
|
|
|
return result.Combined(), result.Error
|
2016-03-04 03:29:24 -05:00
|
|
|
}
|
|
|
|
|
2017-01-19 10:55:51 -05:00
|
|
|
// 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"
|
2017-01-16 10:39:12 -05:00
|
|
|
func (d *Daemon) Command(args ...string) icmd.Cmd {
|
|
|
|
return icmd.Command(d.dockerBinary, d.PrependHostArg(args)...)
|
2016-10-24 17:44:51 -04:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// PrependHostArg prepend the specified arguments by the daemon host flags
|
|
|
|
func (d *Daemon) PrependHostArg(args []string) []string {
|
2016-07-22 12:14:05 -04:00
|
|
|
for _, arg := range args {
|
|
|
|
if arg == "--host" || arg == "-H" {
|
|
|
|
return args
|
|
|
|
}
|
|
|
|
}
|
2016-12-09 04:17:53 -05:00
|
|
|
return append([]string{"--host", d.Sock()}, args...)
|
2016-03-04 03:29:24 -05:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// GetIDByName returns the ID of an object (container, volume, …) given its name
|
|
|
|
func (d *Daemon) GetIDByName(name string) (string, error) {
|
2016-03-04 03:29:24 -05:00
|
|
|
return d.inspectFieldWithError(name, "Id")
|
|
|
|
}
|
|
|
|
|
2016-12-28 20:08:03 -05:00
|
|
|
// InspectField returns the field filter by 'filter'
|
|
|
|
func (d *Daemon) InspectField(name, filter string) (string, error) {
|
|
|
|
return d.inspectFilter(name, filter)
|
|
|
|
}
|
|
|
|
|
2016-03-04 03:29:24 -05:00
|
|
|
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 {
|
2016-12-09 04:18:02 -05:00
|
|
|
return "", errors.Errorf("failed to inspect %s: %s", name, out)
|
2016-03-04 03:29:24 -05:00
|
|
|
}
|
|
|
|
return strings.TrimSpace(out), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Daemon) inspectFieldWithError(name, field string) (string, error) {
|
2022-02-15 06:50:21 -05:00
|
|
|
return d.inspectFilter(name, "."+field)
|
2016-03-04 03:29:24 -05:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckActiveContainerCount returns the number of active containers
|
|
|
|
// FIXME(vdemeester) should re-use ActivateContainers in some way
|
2019-10-21 06:40:22 -04:00
|
|
|
func (d *Daemon) CheckActiveContainerCount(t *testing.T) (interface{}, string) {
|
|
|
|
t.Helper()
|
2016-06-13 22:54:20 -04:00
|
|
|
out, err := d.Cmd("ps", "-q")
|
2019-10-21 06:40:22 -04:00
|
|
|
assert.NilError(t, err)
|
2016-06-13 22:54:20 -04:00
|
|
|
if len(strings.TrimSpace(out)) == 0 {
|
2019-09-09 17:09:27 -04:00
|
|
|
return 0, ""
|
2016-06-13 22:54:20 -04:00
|
|
|
}
|
2019-08-05 11:54:15 -04:00
|
|
|
return len(strings.Split(strings.TrimSpace(out), "\n")), fmt.Sprintf("output: %q", out)
|
2016-06-13 22:54:20 -04:00
|
|
|
}
|
2016-07-28 11:58:06 -04:00
|
|
|
|
2018-04-10 10:29:48 -04:00
|
|
|
// 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...)
|
2017-05-23 23:56:26 -04:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
|
2017-04-11 15:18:30 -04:00
|
|
|
// Deprecated: use cli.WaitCmd instead
|
2016-12-09 04:17:53 -05:00
|
|
|
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 {
|
2016-12-10 03:03:38 -05:00
|
|
|
if !strings.Contains(strings.ToLower(result.Stderr()), "no such") {
|
2016-12-09 04:18:02 -05:00
|
|
|
return errors.Errorf("error executing docker inspect: %v\n%s",
|
2016-12-09 04:17:53 -05:00
|
|
|
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:
|
2016-12-09 04:18:02 -05:00
|
|
|
return errors.Errorf("condition \"%q == %q\" not true in time (%v)", out, expected, timeout)
|
2016-12-09 04:17:53 -05:00
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|