mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
110 lines
3.3 KiB
Go
110 lines
3.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"os"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/docker/docker/api/types"
|
||
|
"github.com/docker/docker/api/types/container"
|
||
|
"github.com/docker/docker/api/types/mount"
|
||
|
"github.com/docker/docker/client"
|
||
|
"github.com/docker/docker/pkg/stdcopy"
|
||
|
)
|
||
|
|
||
|
// testChunkExecutor executes integration-cli binary.
|
||
|
// image needs to be the worker image itself. testFlags are OR-set of regexp for filtering tests.
|
||
|
type testChunkExecutor func(image string, tests []string) (int64, string, error)
|
||
|
|
||
|
func dryTestChunkExecutor(image string, tests []string) (int64, string, error) {
|
||
|
return 0, fmt.Sprintf("DRY RUN (image=%q, tests=%v)", image, tests), nil
|
||
|
}
|
||
|
|
||
|
// privilegedTestChunkExecutor invokes a privileged container from the worker
|
||
|
// service via bind-mounted API socket so as to execute the test chunk
|
||
|
func privilegedTestChunkExecutor(image string, tests []string) (int64, string, error) {
|
||
|
cli, err := client.NewEnvClient()
|
||
|
if err != nil {
|
||
|
return 0, "", err
|
||
|
}
|
||
|
// propagate variables from the host (needs to be defined in the compose file)
|
||
|
experimental := os.Getenv("DOCKER_EXPERIMENTAL")
|
||
|
graphdriver := os.Getenv("DOCKER_GRAPHDRIVER")
|
||
|
if graphdriver == "" {
|
||
|
info, err := cli.Info(context.Background())
|
||
|
if err != nil {
|
||
|
return 0, "", err
|
||
|
}
|
||
|
graphdriver = info.Driver
|
||
|
}
|
||
|
// `daemon_dest` is similar to `$DEST` (e.g. `bundles/VERSION/test-integration-cli`)
|
||
|
// but it exists outside of `bundles` so as to make `$DOCKER_GRAPHDRIVER` work.
|
||
|
//
|
||
|
// Without this hack, `$DOCKER_GRAPHDRIVER` fails because of (e.g.) `overlay2 is not supported over overlayfs`
|
||
|
//
|
||
|
// see integration-cli/daemon/daemon.go
|
||
|
daemonDest := "/daemon_dest"
|
||
|
config := container.Config{
|
||
|
Image: image,
|
||
|
Env: []string{
|
||
|
"TESTFLAGS=-check.f " + strings.Join(tests, "|"),
|
||
|
"KEEPBUNDLE=1",
|
||
|
"DOCKER_INTEGRATION_TESTS_VERIFIED=1", // for avoiding rebuilding integration-cli
|
||
|
"DOCKER_EXPERIMENTAL=" + experimental,
|
||
|
"DOCKER_GRAPHDRIVER=" + graphdriver,
|
||
|
"DOCKER_INTEGRATION_DAEMON_DEST=" + daemonDest,
|
||
|
},
|
||
|
// TODO: set label?
|
||
|
Entrypoint: []string{"hack/dind"},
|
||
|
Cmd: []string{"hack/make.sh", "test-integration-cli"},
|
||
|
}
|
||
|
hostConfig := container.HostConfig{
|
||
|
AutoRemove: true,
|
||
|
Privileged: true,
|
||
|
Mounts: []mount.Mount{
|
||
|
{
|
||
|
Type: mount.TypeVolume,
|
||
|
Target: daemonDest,
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
id, stream, err := runContainer(context.Background(), cli, config, hostConfig)
|
||
|
if err != nil {
|
||
|
return 0, "", err
|
||
|
}
|
||
|
var b bytes.Buffer
|
||
|
teeContainerStream(&b, os.Stdout, os.Stderr, stream)
|
||
|
rc, err := cli.ContainerWait(context.Background(), id)
|
||
|
if err != nil {
|
||
|
return 0, "", err
|
||
|
}
|
||
|
return rc, b.String(), nil
|
||
|
}
|
||
|
|
||
|
func runContainer(ctx context.Context, cli *client.Client, config container.Config, hostConfig container.HostConfig) (string, io.ReadCloser, error) {
|
||
|
created, err := cli.ContainerCreate(context.Background(),
|
||
|
&config, &hostConfig, nil, "")
|
||
|
if err != nil {
|
||
|
return "", nil, err
|
||
|
}
|
||
|
if err = cli.ContainerStart(ctx, created.ID, types.ContainerStartOptions{}); err != nil {
|
||
|
return "", nil, err
|
||
|
}
|
||
|
stream, err := cli.ContainerLogs(ctx,
|
||
|
created.ID,
|
||
|
types.ContainerLogsOptions{
|
||
|
ShowStdout: true,
|
||
|
ShowStderr: true,
|
||
|
Follow: true,
|
||
|
})
|
||
|
return created.ID, stream, err
|
||
|
}
|
||
|
|
||
|
func teeContainerStream(w, stdout, stderr io.Writer, stream io.ReadCloser) {
|
||
|
stdcopy.StdCopy(io.MultiWriter(w, stdout), io.MultiWriter(w, stderr), stream)
|
||
|
stream.Close()
|
||
|
}
|