aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorSam Whited <sam@samwhited.com>2019-08-29 15:52:40 -0500
committerSam Whited <sam@samwhited.com>2019-09-11 07:47:23 -0500
commitb37c214e3c8c4ff5450bd5fc1225d53827d240e7 (patch)
tree5687180effbed0fef2b57743bbf210fd7fd71af2 /internal
parentcd9e4ec24002fcf3238c1f1e8629e08966c2b7fb (diff)
testutil: make testing packages public
This was done with something along the lines of: ``` mv internal/test testutil pushd testutil/; grep -IRl "package test" | xargs -I '{}' sed -i -e 's|package test|package testutil|g' {}; popd mv internal/testutil/*.go testutil/ && rm -rf internal/ grep -IRl "github.com\/docker\/docker\/internal\/test" | xargs -I '{}' sed -i -e 's|github.com/docker/docker/internal/test|github.com/docker/docker/test|g' {} goimports . ``` I also modified the basic plugin path in testutil/fixtures/plugin. Signed-off-by: Sam Whited <sam@samwhited.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/test/daemon/config.go82
-rw-r--r--internal/test/daemon/container.go40
-rw-r--r--internal/test/daemon/daemon.go738
-rw-r--r--internal/test/daemon/daemon_unix.go50
-rw-r--r--internal/test/daemon/daemon_windows.go32
-rw-r--r--internal/test/daemon/node.go89
-rw-r--r--internal/test/daemon/ops.go79
-rw-r--r--internal/test/daemon/ops_unix.go34
-rw-r--r--internal/test/daemon/plugin.go75
-rw-r--r--internal/test/daemon/secret.go84
-rw-r--r--internal/test/daemon/service.go134
-rw-r--r--internal/test/daemon/swarm.go223
-rw-r--r--internal/test/environment/clean.go207
-rw-r--r--internal/test/environment/environment.go195
-rw-r--r--internal/test/environment/protect.go254
-rw-r--r--internal/test/fakecontext/context.go131
-rw-r--r--internal/test/fakegit/fakegit.go136
-rw-r--r--internal/test/fakestorage/fixtures.go92
-rw-r--r--internal/test/fakestorage/storage.go200
-rw-r--r--internal/test/fixtures/load/frozen.go196
-rw-r--r--internal/test/fixtures/plugin/basic/basic.go34
-rw-r--r--internal/test/fixtures/plugin/plugin.go216
-rw-r--r--internal/test/helper.go6
-rw-r--r--internal/test/registry/ops.go26
-rw-r--r--internal/test/registry/registry.go255
-rw-r--r--internal/test/registry/registry_mock.go71
-rw-r--r--internal/test/request/npipe.go12
-rw-r--r--internal/test/request/npipe_windows.go12
-rw-r--r--internal/test/request/ops.go78
-rw-r--r--internal/test/request/request.go223
-rw-r--r--internal/testutil/helpers.go17
-rw-r--r--internal/testutil/stringutils.go14
-rw-r--r--internal/testutil/stringutils_test.go34
33 files changed, 0 insertions, 4069 deletions
diff --git a/internal/test/daemon/config.go b/internal/test/daemon/config.go
deleted file mode 100644
index ce99222b37..0000000000
--- a/internal/test/daemon/config.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package daemon
-
-import (
- "context"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-// ConfigConstructor defines a swarm config constructor
-type ConfigConstructor func(*swarm.Config)
-
-// CreateConfig creates a config given the specified spec
-func (d *Daemon) CreateConfig(t assert.TestingT, configSpec swarm.ConfigSpec) string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- scr, err := cli.ConfigCreate(context.Background(), configSpec)
- assert.NilError(t, err)
- return scr.ID
-}
-
-// ListConfigs returns the list of the current swarm configs
-func (d *Daemon) ListConfigs(t assert.TestingT) []swarm.Config {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- configs, err := cli.ConfigList(context.Background(), types.ConfigListOptions{})
- assert.NilError(t, err)
- return configs
-}
-
-// GetConfig returns a swarm config identified by the specified id
-func (d *Daemon) GetConfig(t assert.TestingT, id string) *swarm.Config {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- config, _, err := cli.ConfigInspectWithRaw(context.Background(), id)
- assert.NilError(t, err)
- return &config
-}
-
-// DeleteConfig removes the swarm config identified by the specified id
-func (d *Daemon) DeleteConfig(t assert.TestingT, id string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- err := cli.ConfigRemove(context.Background(), id)
- assert.NilError(t, err)
-}
-
-// UpdateConfig updates the swarm config identified by the specified id
-// Currently, only label update is supported.
-func (d *Daemon) UpdateConfig(t assert.TestingT, id string, f ...ConfigConstructor) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- config := d.GetConfig(t, id)
- for _, fn := range f {
- fn(config)
- }
-
- err := cli.ConfigUpdate(context.Background(), config.ID, config.Version, config.Spec)
- assert.NilError(t, err)
-}
diff --git a/internal/test/daemon/container.go b/internal/test/daemon/container.go
deleted file mode 100644
index 3aa69e195c..0000000000
--- a/internal/test/daemon/container.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package daemon
-
-import (
- "context"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-// ActiveContainers returns the list of ids of the currently running containers
-func (d *Daemon) ActiveContainers(t assert.TestingT) []string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
- assert.NilError(t, err)
-
- ids := make([]string, len(containers))
- for i, c := range containers {
- ids[i] = c.ID
- }
- return ids
-}
-
-// FindContainerIP returns the ip of the specified container
-func (d *Daemon) FindContainerIP(t assert.TestingT, id string) string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- i, err := cli.ContainerInspect(context.Background(), id)
- assert.NilError(t, err)
- return i.NetworkSettings.IPAddress
-}
diff --git a/internal/test/daemon/daemon.go b/internal/test/daemon/daemon.go
deleted file mode 100644
index b3ea876ccc..0000000000
--- a/internal/test/daemon/daemon.go
+++ /dev/null
@@ -1,738 +0,0 @@
-package daemon // import "github.com/docker/docker/internal/test/daemon"
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "os/exec"
- "path/filepath"
- "strconv"
- "strings"
- "time"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/events"
- "github.com/docker/docker/client"
- "github.com/docker/docker/daemon/images"
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/internal/test/request"
- "github.com/docker/docker/opts"
- "github.com/docker/docker/pkg/ioutils"
- "github.com/docker/docker/pkg/stringid"
- "github.com/docker/go-connections/sockets"
- "github.com/docker/go-connections/tlsconfig"
- "github.com/pkg/errors"
- "gotest.tools/assert"
-)
-
-type testingT interface {
- assert.TestingT
- logT
- Fatalf(string, ...interface{})
-}
-
-type namer interface {
- Name() string
-}
-type testNamer interface {
- TestName() string
-}
-
-type logT interface {
- Logf(string, ...interface{})
-}
-
-const defaultDockerdBinary = "dockerd"
-const containerdSocket = "/var/run/docker/containerd/containerd.sock"
-
-var errDaemonNotStarted = errors.New("daemon not started")
-
-// SockRoot holds the path of the default docker integration daemon socket
-var SockRoot = filepath.Join(os.TempDir(), "docker-integration")
-
-type clientConfig struct {
- transport *http.Transport
- scheme string
- addr string
-}
-
-// Daemon represents a Docker daemon for the testing framework
-type Daemon struct {
- GlobalFlags []string
- Root string
- Folder string
- Wait chan error
- UseDefaultHost bool
- UseDefaultTLSHost bool
-
- id string
- logFile *os.File
- cmd *exec.Cmd
- storageDriver string
- userlandProxy bool
- defaultCgroupNamespaceMode string
- execRoot string
- experimental bool
- init bool
- dockerdBinary string
- log logT
- imageService *images.ImageService
-
- // swarm related field
- swarmListenAddr string
- SwarmPort int // FIXME(vdemeester) should probably not be exported
- DefaultAddrPool []string
- SubnetSize uint32
- DataPathPort uint32
- // cached information
- CachedInfo types.Info
-}
-
-// New returns a Daemon instance to be used for testing.
-// 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, ops ...func(*Daemon)) *Daemon {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- dest := os.Getenv("DOCKER_INTEGRATION_DAEMON_DEST")
- if dest == "" {
- dest = os.Getenv("DEST")
- }
- switch v := t.(type) {
- case namer:
- dest = filepath.Join(dest, v.Name())
- case testNamer:
- dest = filepath.Join(dest, v.TestName())
- }
- t.Logf("Creating a new daemon at: %s", dest)
- assert.Check(t, dest != "", "Please set the DOCKER_INTEGRATION_DAEMON_DEST or the DEST environment variable")
-
- storageDriver := os.Getenv("DOCKER_GRAPHDRIVER")
-
- assert.NilError(t, os.MkdirAll(SockRoot, 0700), "could not create daemon socket root")
-
- id := fmt.Sprintf("d%s", stringid.TruncateID(stringid.GenerateRandomID()))
- dir := filepath.Join(dest, id)
- daemonFolder, err := filepath.Abs(dir)
- assert.NilError(t, err, "Could not make %q an absolute path", dir)
- daemonRoot := filepath.Join(daemonFolder, "root")
-
- assert.NilError(t, os.MkdirAll(daemonRoot, 0755), "Could not create daemon root %q", dir)
-
- userlandProxy := true
- if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
- if val, err := strconv.ParseBool(env); err != nil {
- userlandProxy = val
- }
- }
- d := &Daemon{
- id: id,
- Folder: daemonFolder,
- Root: daemonRoot,
- storageDriver: storageDriver,
- userlandProxy: userlandProxy,
- // dxr stands for docker-execroot (shortened for avoiding unix(7) path length limitation)
- execRoot: filepath.Join(os.TempDir(), "dxr", id),
- dockerdBinary: defaultDockerdBinary,
- swarmListenAddr: defaultSwarmListenAddr,
- SwarmPort: DefaultSwarmPort,
- log: t,
- }
-
- for _, op := range ops {
- op(d)
- }
-
- return d
-}
-
-// ContainersNamespace returns the containerd namespace used for containers.
-func (d *Daemon) ContainersNamespace() string {
- return d.id
-}
-
-// RootDir returns the root directory of the daemon.
-func (d *Daemon) RootDir() string {
- return d.Root
-}
-
-// ID returns the generated id of the daemon
-func (d *Daemon) ID() string {
- return d.id
-}
-
-// StorageDriver returns the configured storage driver of the daemon
-func (d *Daemon) StorageDriver() string {
- return d.storageDriver
-}
-
-// Sock returns the socket path of the daemon
-func (d *Daemon) Sock() string {
- return fmt.Sprintf("unix://" + d.sockPath())
-}
-
-func (d *Daemon) sockPath() string {
- return filepath.Join(SockRoot, d.id+".sock")
-}
-
-// LogFileName returns the path the daemon's log file
-func (d *Daemon) LogFileName() string {
- return d.logFile.Name()
-}
-
-// ReadLogFile returns the content of the daemon log file
-func (d *Daemon) ReadLogFile() ([]byte, error) {
- return ioutil.ReadFile(d.logFile.Name())
-}
-
-// NewClientT creates new client based on daemon's socket path
-func (d *Daemon) NewClientT(t assert.TestingT, extraOpts ...client.Opt) *client.Client {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
-
- clientOpts := []client.Opt{
- client.FromEnv,
- client.WithHost(d.Sock()),
- }
- clientOpts = append(clientOpts, extraOpts...)
-
- c, err := client.NewClientWithOpts(clientOpts...)
- assert.NilError(t, err, "cannot create daemon client")
- return c
-}
-
-// Cleanup cleans the daemon files : exec root (network namespaces, ...), swarmkit files
-func (d *Daemon) Cleanup(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- // Cleanup swarmkit wal files if present
- cleanupRaftDir(t, d.Root)
- cleanupNetworkNamespace(t, d.execRoot)
-}
-
-// Start starts the daemon and return once it is ready to receive requests.
-func (d *Daemon) Start(t testingT, args ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- if err := d.StartWithError(args...); err != nil {
- t.Fatalf("failed to start daemon with arguments %v : %v", args, err)
- }
-}
-
-// StartWithError starts the daemon and return once it is ready to receive requests.
-// It returns an error in case it couldn't start.
-func (d *Daemon) StartWithError(args ...string) error {
- logFile, err := os.OpenFile(filepath.Join(d.Folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
- if err != nil {
- return errors.Wrapf(err, "[%s] Could not create %s/docker.log", d.id, d.Folder)
- }
-
- return d.StartWithLogFile(logFile, args...)
-}
-
-// StartWithLogFile will start the daemon and attach its streams to a given file.
-func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error {
- d.handleUserns()
- dockerdBinary, err := exec.LookPath(d.dockerdBinary)
- if err != nil {
- return errors.Wrapf(err, "[%s] could not find docker binary in $PATH", d.id)
- }
-
- args := append(d.GlobalFlags,
- "--containerd", containerdSocket,
- "--data-root", d.Root,
- "--exec-root", d.execRoot,
- "--pidfile", fmt.Sprintf("%s/docker.pid", d.Folder),
- fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
- "--containerd-namespace", d.id,
- "--containerd-plugins-namespace", d.id+"p",
- )
- if d.defaultCgroupNamespaceMode != "" {
- args = append(args, []string{"--default-cgroupns-mode", d.defaultCgroupNamespaceMode}...)
- }
- if d.experimental {
- args = append(args, "--experimental")
- }
- if d.init {
- args = append(args, "--init")
- }
- if !(d.UseDefaultHost || d.UseDefaultTLSHost) {
- args = append(args, []string{"--host", d.Sock()}...)
- }
- if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
- args = append(args, []string{"--userns-remap", root}...)
- }
-
- // If we don't explicitly set the log-level or debug flag(-D) then
- // turn on debug mode
- foundLog := false
- foundSd := false
- for _, a := range providedArgs {
- if strings.Contains(a, "--log-level") || strings.Contains(a, "-D") || strings.Contains(a, "--debug") {
- foundLog = true
- }
- if strings.Contains(a, "--storage-driver") {
- foundSd = true
- }
- }
- if !foundLog {
- args = append(args, "--debug")
- }
- if d.storageDriver != "" && !foundSd {
- args = append(args, "--storage-driver", d.storageDriver)
- }
-
- args = append(args, providedArgs...)
- d.cmd = exec.Command(dockerdBinary, args...)
- d.cmd.Env = append(os.Environ(), "DOCKER_SERVICE_PREFER_OFFLINE_IMAGE=1")
- d.cmd.Stdout = out
- d.cmd.Stderr = out
- d.logFile = out
-
- if err := d.cmd.Start(); err != nil {
- return errors.Errorf("[%s] could not start daemon container: %v", d.id, err)
- }
-
- wait := make(chan error, 1)
-
- go func() {
- ret := d.cmd.Wait()
- d.log.Logf("[%s] exiting daemon", d.id)
- // If we send before logging, we might accidentally log _after_ the test is done.
- // As of Go 1.12, this incurs a panic instead of silently being dropped.
- wait <- ret
- close(wait)
- }()
-
- d.Wait = wait
-
- clientConfig, err := d.getClientConfig()
- if err != nil {
- return err
- }
- client := &http.Client{
- Transport: clientConfig.transport,
- }
-
- req, err := http.NewRequest("GET", "/_ping", nil)
- if err != nil {
- return errors.Wrapf(err, "[%s] could not create new request", d.id)
- }
- req.URL.Host = clientConfig.addr
- req.URL.Scheme = clientConfig.scheme
-
- ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
- defer cancel()
-
- // make sure daemon is ready to receive requests
- for i := 0; ; i++ {
- d.log.Logf("[%s] waiting for daemon to start", d.id)
-
- select {
- case <-ctx.Done():
- return errors.Errorf("[%s] Daemon exited and never started: %s", d.id, ctx.Err())
- case err := <-d.Wait:
- return errors.Errorf("[%s] Daemon exited during startup: %v", d.id, err)
- default:
- rctx, rcancel := context.WithTimeout(context.TODO(), 2*time.Second)
- defer rcancel()
-
- resp, err := client.Do(req.WithContext(rctx))
- if err != nil {
- if i > 2 { // don't log the first couple, this ends up just being noise
- d.log.Logf("[%s] error pinging daemon on start: %v", d.id, err)
- }
-
- select {
- case <-ctx.Done():
- case <-time.After(500 * time.Millisecond):
- }
- continue
- }
-
- resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- d.log.Logf("[%s] received status != 200 OK: %s\n", d.id, resp.Status)
- }
- d.log.Logf("[%s] daemon started\n", d.id)
- d.Root, err = d.queryRootDir()
- if err != nil {
- return errors.Errorf("[%s] error querying daemon for root directory: %v", d.id, err)
- }
- return nil
- }
- }
-}
-
-// StartWithBusybox will first start the daemon with Daemon.Start()
-// then save the busybox image from the main daemon and load it into this Daemon instance.
-func (d *Daemon) StartWithBusybox(t testingT, arg ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- d.Start(t, arg...)
- d.LoadBusybox(t)
-}
-
-// Kill will send a SIGKILL to the daemon
-func (d *Daemon) Kill() error {
- if d.cmd == nil || d.Wait == nil {
- return errDaemonNotStarted
- }
-
- defer func() {
- d.logFile.Close()
- d.cmd = nil
- }()
-
- if err := d.cmd.Process.Kill(); err != nil {
- return err
- }
-
- return os.Remove(fmt.Sprintf("%s/docker.pid", d.Folder))
-}
-
-// Pid returns the pid of the daemon
-func (d *Daemon) Pid() int {
- return d.cmd.Process.Pid
-}
-
-// Interrupt stops the daemon by sending it an Interrupt signal
-func (d *Daemon) Interrupt() error {
- return d.Signal(os.Interrupt)
-}
-
-// Signal sends the specified signal to the daemon if running
-func (d *Daemon) Signal(signal os.Signal) error {
- if d.cmd == nil || d.Wait == nil {
- return errDaemonNotStarted
- }
- return d.cmd.Process.Signal(signal)
-}
-
-// DumpStackAndQuit sends SIGQUIT to the daemon, which triggers it to dump its
-// stack to its log file and exit
-// This is used primarily for gathering debug information on test timeout
-func (d *Daemon) DumpStackAndQuit() {
- if d.cmd == nil || d.cmd.Process == nil {
- return
- }
- SignalDaemonDump(d.cmd.Process.Pid)
-}
-
-// Stop will send a SIGINT every second and wait for the daemon to stop.
-// If it times out, a SIGKILL is sent.
-// Stop will not delete the daemon directory. If a purged daemon is needed,
-// instantiate a new one with NewDaemon.
-// If an error occurs while starting the daemon, the test will fail.
-func (d *Daemon) Stop(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- err := d.StopWithError()
- if err != nil {
- if err != errDaemonNotStarted {
- t.Fatalf("Error while stopping the daemon %s : %v", d.id, err)
- } else {
- t.Logf("Daemon %s is not started", d.id)
- }
- }
-}
-
-// StopWithError will send a SIGINT every second and wait for the daemon to stop.
-// If it timeouts, a SIGKILL is sent.
-// Stop will not delete the daemon directory. If a purged daemon is needed,
-// instantiate a new one with NewDaemon.
-func (d *Daemon) StopWithError() (err error) {
- if d.cmd == nil || d.Wait == nil {
- return errDaemonNotStarted
- }
- defer func() {
- if err == nil {
- d.log.Logf("[%s] Daemon stopped", d.id)
- } else {
- d.log.Logf("[%s] Error when stopping daemon: %v", d.id, err)
- }
- d.logFile.Close()
- d.cmd = nil
- }()
-
- i := 1
- ticker := time.NewTicker(time.Second)
- defer ticker.Stop()
- tick := ticker.C
-
- d.log.Logf("[%s] Stopping daemon", d.id)
-
- if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
- if strings.Contains(err.Error(), "os: process already finished") {
- return errDaemonNotStarted
- }
- return errors.Errorf("could not send signal: %v", err)
- }
-
-out1:
- for {
- select {
- case err := <-d.Wait:
- return err
- case <-time.After(20 * time.Second):
- // time for stopping jobs and run onShutdown hooks
- d.log.Logf("[%s] daemon stop timeout", d.id)
- break out1
- }
- }
-
-out2:
- for {
- select {
- case err := <-d.Wait:
- return err
- case <-tick:
- i++
- if i > 5 {
- d.log.Logf("tried to interrupt daemon for %d times, now try to kill it", i)
- break out2
- }
- d.log.Logf("Attempt #%d: daemon is still running with pid %d", i, d.cmd.Process.Pid)
- if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
- return errors.Errorf("could not send signal: %v", err)
- }
- }
- }
-
- if err := d.cmd.Process.Kill(); err != nil {
- d.log.Logf("Could not kill daemon: %v", err)
- return err
- }
-
- d.cmd.Wait()
-
- return os.Remove(fmt.Sprintf("%s/docker.pid", d.Folder))
-}
-
-// Restart will restart the daemon by first stopping it and the starting it.
-// If an error occurs while starting the daemon, the test will fail.
-func (d *Daemon) Restart(t testingT, args ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- d.Stop(t)
- d.Start(t, args...)
-}
-
-// RestartWithError will restart the daemon by first stopping it and then starting it.
-func (d *Daemon) RestartWithError(arg ...string) error {
- if err := d.StopWithError(); err != nil {
- return err
- }
- return d.StartWithError(arg...)
-}
-
-func (d *Daemon) handleUserns() {
- // in the case of tests running a user namespace-enabled daemon, we have resolved
- // d.Root to be the actual final path of the graph dir after the "uid.gid" of
- // remapped root is added--we need to subtract it from the path before calling
- // start or else we will continue making subdirectories rather than truly restarting
- // with the same location/root:
- if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
- d.Root = filepath.Dir(d.Root)
- }
-}
-
-// ReloadConfig asks the daemon to reload its configuration
-func (d *Daemon) ReloadConfig() error {
- if d.cmd == nil || d.cmd.Process == nil {
- return errors.New("daemon is not running")
- }
-
- errCh := make(chan error)
- started := make(chan struct{})
- go func() {
- _, body, err := request.Get("/events", request.Host(d.Sock()))
- close(started)
- if err != nil {
- errCh <- err
- }
- defer body.Close()
- dec := json.NewDecoder(body)
- for {
- var e events.Message
- if err := dec.Decode(&e); err != nil {
- errCh <- err
- return
- }
- if e.Type != events.DaemonEventType {
- continue
- }
- if e.Action != "reload" {
- continue
- }
- close(errCh) // notify that we are done
- return
- }
- }()
-
- <-started
- if err := signalDaemonReload(d.cmd.Process.Pid); err != nil {
- return errors.Errorf("error signaling daemon reload: %v", err)
- }
- select {
- case err := <-errCh:
- if err != nil {
- return errors.Errorf("error waiting for daemon reload event: %v", err)
- }
- case <-time.After(30 * time.Second):
- return errors.New("timeout waiting for daemon reload event")
- }
- return nil
-}
-
-// LoadBusybox image into the daemon
-func (d *Daemon) LoadBusybox(t assert.TestingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- clientHost, err := client.NewClientWithOpts(client.FromEnv)
- assert.NilError(t, err, "failed to create client")
- defer clientHost.Close()
-
- ctx := context.Background()
- reader, err := clientHost.ImageSave(ctx, []string{"busybox:latest"})
- assert.NilError(t, err, "failed to download busybox")
- defer reader.Close()
-
- c := d.NewClientT(t)
- defer c.Close()
-
- resp, err := c.ImageLoad(ctx, reader, true)
- assert.NilError(t, err, "failed to load busybox")
- defer resp.Body.Close()
-}
-
-func (d *Daemon) getClientConfig() (*clientConfig, error) {
- var (
- transport *http.Transport
- scheme string
- addr string
- proto string
- )
- if d.UseDefaultTLSHost {
- option := &tlsconfig.Options{
- CAFile: "fixtures/https/ca.pem",
- CertFile: "fixtures/https/client-cert.pem",
- KeyFile: "fixtures/https/client-key.pem",
- }
- tlsConfig, err := tlsconfig.Client(*option)
- if err != nil {
- return nil, err
- }
- transport = &http.Transport{
- TLSClientConfig: tlsConfig,
- }
- addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort)
- scheme = "https"
- proto = "tcp"
- } else if d.UseDefaultHost {
- addr = opts.DefaultUnixSocket
- proto = "unix"
- scheme = "http"
- transport = &http.Transport{}
- } else {
- addr = d.sockPath()
- proto = "unix"
- scheme = "http"
- transport = &http.Transport{}
- }
-
- if err := sockets.ConfigureTransport(transport, proto, addr); err != nil {
- return nil, err
- }
- transport.DisableKeepAlives = true
- if proto == "unix" {
- addr = filepath.Base(addr)
- }
- return &clientConfig{
- transport: transport,
- scheme: scheme,
- addr: addr,
- }, nil
-}
-
-func (d *Daemon) queryRootDir() (string, error) {
- // update daemon root by asking /info endpoint (to support user
- // namespaced daemon with root remapped uid.gid directory)
- clientConfig, err := d.getClientConfig()
- if err != nil {
- return "", err
- }
-
- c := &http.Client{
- Transport: clientConfig.transport,
- }
-
- req, err := http.NewRequest("GET", "/info", nil)
- if err != nil {
- return "", err
- }
- req.Header.Set("Content-Type", "application/json")
- req.URL.Host = clientConfig.addr
- req.URL.Scheme = clientConfig.scheme
-
- resp, err := c.Do(req)
- if err != nil {
- return "", err
- }
- body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
- return resp.Body.Close()
- })
-
- type Info struct {
- DockerRootDir string
- }
- var b []byte
- var i Info
- b, err = request.ReadBody(body)
- if err == nil && resp.StatusCode == http.StatusOK {
- // read the docker root dir
- if err = json.Unmarshal(b, &i); err == nil {
- return i.DockerRootDir, nil
- }
- }
- return "", err
-}
-
-// Info returns the info struct for this daemon
-func (d *Daemon) Info(t assert.TestingT) types.Info {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- c := d.NewClientT(t)
- info, err := c.Info(context.Background())
- assert.NilError(t, err)
- return info
-}
-
-func cleanupRaftDir(t testingT, rootPath string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- for _, p := range []string{"wal", "wal-v3-encrypted", "snap-v3-encrypted"} {
- dir := filepath.Join(rootPath, "swarm/raft", p)
- if err := os.RemoveAll(dir); err != nil {
- t.Logf("error removing %v: %v", dir, err)
- }
- }
-}
-
-// ImageService returns the Daemon's ImageService
-func (d *Daemon) ImageService() *images.ImageService {
- return d.imageService
-}
diff --git a/internal/test/daemon/daemon_unix.go b/internal/test/daemon/daemon_unix.go
deleted file mode 100644
index 7c2b15c1ad..0000000000
--- a/internal/test/daemon/daemon_unix.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// +build !windows
-
-package daemon // import "github.com/docker/docker/internal/test/daemon"
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/docker/docker/internal/test"
- "golang.org/x/sys/unix"
- "gotest.tools/assert"
-)
-
-func cleanupNetworkNamespace(t testingT, execRoot string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- // Cleanup network namespaces in the exec root of this
- // daemon because this exec root is specific to this
- // daemon instance and has no chance of getting
- // cleaned up when a new daemon is instantiated with a
- // new exec root.
- netnsPath := filepath.Join(execRoot, "netns")
- filepath.Walk(netnsPath, func(path string, info os.FileInfo, err error) error {
- if err := unix.Unmount(path, unix.MNT_DETACH); err != nil && err != unix.EINVAL && err != unix.ENOENT {
- t.Logf("unmount of %s failed: %v", path, err)
- }
- os.Remove(path)
- return nil
- })
-}
-
-// CgroupNamespace returns the cgroup namespace the daemon is running in
-func (d *Daemon) CgroupNamespace(t assert.TestingT) string {
- link, err := os.Readlink(fmt.Sprintf("/proc/%d/ns/cgroup", d.Pid()))
- assert.NilError(t, err)
-
- return strings.TrimSpace(link)
-}
-
-// SignalDaemonDump sends a signal to the daemon to write a dump file
-func SignalDaemonDump(pid int) {
- unix.Kill(pid, unix.SIGQUIT)
-}
-
-func signalDaemonReload(pid int) error {
- return unix.Kill(pid, unix.SIGHUP)
-}
diff --git a/internal/test/daemon/daemon_windows.go b/internal/test/daemon/daemon_windows.go
deleted file mode 100644
index a7e987c92f..0000000000
--- a/internal/test/daemon/daemon_windows.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package daemon // import "github.com/docker/docker/internal/test/daemon"
-
-import (
- "fmt"
- "strconv"
-
- "golang.org/x/sys/windows"
- "gotest.tools/assert"
-)
-
-// SignalDaemonDump sends a signal to the daemon to write a dump file
-func SignalDaemonDump(pid int) {
- ev, _ := windows.UTF16PtrFromString("Global\\docker-daemon-" + strconv.Itoa(pid))
- h2, err := windows.OpenEvent(0x0002, false, ev)
- if h2 == 0 || err != nil {
- return
- }
- windows.PulseEvent(h2)
-}
-
-func signalDaemonReload(pid int) error {
- return fmt.Errorf("daemon reload not supported")
-}
-
-func cleanupNetworkNamespace(t testingT, execRoot string) {
-}
-
-// CgroupNamespace returns the cgroup namespace the daemon is running in
-func (d *Daemon) CgroupNamespace(t assert.TestingT) string {
- assert.Assert(t, false)
- return "cgroup namespaces are not supported on Windows"
-}
diff --git a/internal/test/daemon/node.go b/internal/test/daemon/node.go
deleted file mode 100644
index d5f6f15263..0000000000
--- a/internal/test/daemon/node.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package daemon
-
-import (
- "context"
- "strings"
- "time"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-// NodeConstructor defines a swarm node constructor
-type NodeConstructor func(*swarm.Node)
-
-// GetNode returns a swarm node identified by the specified id
-func (d *Daemon) GetNode(t assert.TestingT, id string, errCheck ...func(error) bool) *swarm.Node {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- node, _, err := cli.NodeInspectWithRaw(context.Background(), id)
- if err != nil {
- for _, f := range errCheck {
- if f(err) {
- return nil
- }
- }
- }
- assert.NilError(t, err, "[%s] (*Daemon).GetNode: NodeInspectWithRaw(%q) failed", d.id, id)
- assert.Check(t, node.ID == id)
- return &node
-}
-
-// RemoveNode removes the specified node
-func (d *Daemon) RemoveNode(t assert.TestingT, id string, force bool) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- options := types.NodeRemoveOptions{
- Force: force,
- }
- err := cli.NodeRemove(context.Background(), id, options)
- assert.NilError(t, err)
-}
-
-// UpdateNode updates a swarm node with the specified node constructor
-func (d *Daemon) UpdateNode(t assert.TestingT, id string, f ...NodeConstructor) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- for i := 0; ; i++ {
- node := d.GetNode(t, id)
- for _, fn := range f {
- fn(node)
- }
-
- err := cli.NodeUpdate(context.Background(), node.ID, node.Version, node.Spec)
- if i < 10 && err != nil && strings.Contains(err.Error(), "update out of sequence") {
- time.Sleep(100 * time.Millisecond)
- continue
- }
- assert.NilError(t, err)
- return
- }
-}
-
-// ListNodes returns the list of the current swarm nodes
-func (d *Daemon) ListNodes(t assert.TestingT) []swarm.Node {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- nodes, err := cli.NodeList(context.Background(), types.NodeListOptions{})
- assert.NilError(t, err)
-
- return nodes
-}
diff --git a/internal/test/daemon/ops.go b/internal/test/daemon/ops.go
deleted file mode 100644
index 9f869dee0f..0000000000
--- a/internal/test/daemon/ops.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package daemon
-
-import "github.com/docker/docker/internal/test/environment"
-
-// WithDefaultCgroupNamespaceMode sets the default cgroup namespace mode for the daemon
-func WithDefaultCgroupNamespaceMode(mode string) func(*Daemon) {
- return func(d *Daemon) {
- d.defaultCgroupNamespaceMode = mode
- }
-}
-
-// WithExperimental sets the daemon in experimental mode
-func WithExperimental(d *Daemon) {
- d.experimental = true
- d.init = true
-}
-
-// WithInit sets the daemon init
-func WithInit(d *Daemon) {
- d.init = true
-}
-
-// WithDockerdBinary sets the dockerd binary to the specified one
-func WithDockerdBinary(dockerdBinary string) func(*Daemon) {
- return func(d *Daemon) {
- d.dockerdBinary = dockerdBinary
- }
-}
-
-// WithSwarmPort sets the swarm port to use for swarm mode
-func WithSwarmPort(port int) func(*Daemon) {
- return func(d *Daemon) {
- d.SwarmPort = port
- }
-}
-
-// WithSwarmListenAddr sets the swarm listen addr to use for swarm mode
-func WithSwarmListenAddr(listenAddr string) func(*Daemon) {
- return func(d *Daemon) {
- d.swarmListenAddr = listenAddr
- }
-}
-
-// WithSwarmDefaultAddrPool sets the swarm default address pool to use for swarm mode
-func WithSwarmDefaultAddrPool(defaultAddrPool []string) func(*Daemon) {
- return func(d *Daemon) {
- d.DefaultAddrPool = defaultAddrPool
- }
-}
-
-// WithSwarmDefaultAddrPoolSubnetSize sets the subnet length mask of swarm default address pool to use for swarm mode
-func WithSwarmDefaultAddrPoolSubnetSize(subnetSize uint32) func(*Daemon) {
- return func(d *Daemon) {
- d.SubnetSize = subnetSize
- }
-}
-
-// WithSwarmDataPathPort sets the swarm datapath port to use for swarm mode
-func WithSwarmDataPathPort(datapathPort uint32) func(*Daemon) {
- return func(d *Daemon) {
- d.DataPathPort = datapathPort
- }
-}
-
-// WithEnvironment sets options from internal/test/environment.Execution struct
-func WithEnvironment(e environment.Execution) func(*Daemon) {
- return func(d *Daemon) {
- if e.DaemonInfo.ExperimentalBuild {
- d.experimental = true
- }
- }
-}
-
-// WithStorageDriver sets store driver option
-func WithStorageDriver(driver string) func(d *Daemon) {
- return func(d *Daemon) {
- d.storageDriver = driver
- }
-}
diff --git a/internal/test/daemon/ops_unix.go b/internal/test/daemon/ops_unix.go
deleted file mode 100644
index 41011e87c5..0000000000
--- a/internal/test/daemon/ops_unix.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// +build !windows
-
-package daemon
-
-import (
- "path/filepath"
- "runtime"
-
- "github.com/docker/docker/daemon/images"
- "github.com/docker/docker/layer"
-
- // register graph drivers
- _ "github.com/docker/docker/daemon/graphdriver/register"
- "github.com/docker/docker/pkg/idtools"
-)
-
-// WithImageService sets imageService options
-func WithImageService(d *Daemon) {
- layerStores := make(map[string]layer.Store)
- os := runtime.GOOS
- layerStores[os], _ = layer.NewStoreFromOptions(layer.StoreOptions{
- Root: d.Root,
- MetadataStorePathTemplate: filepath.Join(d.RootDir(), "image", "%s", "layerdb"),
- GraphDriver: d.storageDriver,
- GraphDriverOptions: nil,
- IDMapping: &idtools.IdentityMapping{},
- PluginGetter: nil,
- ExperimentalEnabled: false,
- OS: os,
- })
- d.imageService = images.NewImageService(images.ImageServiceConfig{
- LayerStores: layerStores,
- })
-}
diff --git a/internal/test/daemon/plugin.go b/internal/test/daemon/plugin.go
deleted file mode 100644
index ad66ebbf07..0000000000
--- a/internal/test/daemon/plugin.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package daemon
-
-import (
- "context"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/client"
- "gotest.tools/assert"
- "gotest.tools/poll"
-)
-
-// PluginIsRunning provides a poller to check if the specified plugin is running
-func (d *Daemon) PluginIsRunning(t assert.TestingT, name string) func(poll.LogT) poll.Result {
- return withClient(t, d, withPluginInspect(name, func(plugin *types.Plugin, t poll.LogT) poll.Result {
- if plugin.Enabled {
- return poll.Success()
- }
- return poll.Continue("plugin %q is not enabled", name)
- }))
-}
-
-// PluginIsNotRunning provides a poller to check if the specified plugin is not running
-func (d *Daemon) PluginIsNotRunning(t assert.TestingT, name string) func(poll.LogT) poll.Result {
- return withClient(t, d, withPluginInspect(name, func(plugin *types.Plugin, t poll.LogT) poll.Result {
- if !plugin.Enabled {
- return poll.Success()
- }
- return poll.Continue("plugin %q is enabled", name)
- }))
-}
-
-// PluginIsNotPresent provides a poller to check if the specified plugin is not present
-func (d *Daemon) PluginIsNotPresent(t assert.TestingT, name string) func(poll.LogT) poll.Result {
- return withClient(t, d, func(c client.APIClient, t poll.LogT) poll.Result {
- _, _, err := c.PluginInspectWithRaw(context.Background(), name)
- if client.IsErrNotFound(err) {
- return poll.Success()
- }
- if err != nil {
- return poll.Error(err)
- }
- return poll.Continue("plugin %q exists", name)
- })
-}
-
-// PluginReferenceIs provides a poller to check if the specified plugin has the specified reference
-func (d *Daemon) PluginReferenceIs(t assert.TestingT, name, expectedRef string) func(poll.LogT) poll.Result {
- return withClient(t, d, withPluginInspect(name, func(plugin *types.Plugin, t poll.LogT) poll.Result {
- if plugin.PluginReference == expectedRef {
- return poll.Success()
- }
- return poll.Continue("plugin %q reference is not %q", name, expectedRef)
- }))
-}
-
-func withPluginInspect(name string, f func(*types.Plugin, poll.LogT) poll.Result) func(client.APIClient, poll.LogT) poll.Result {
- return func(c client.APIClient, t poll.LogT) poll.Result {
- plugin, _, err := c.PluginInspectWithRaw(context.Background(), name)
- if client.IsErrNotFound(err) {
- return poll.Continue("plugin %q not found", name)
- }
- if err != nil {
- return poll.Error(err)
- }
- return f(plugin, t)
- }
-
-}
-
-func withClient(t assert.TestingT, d *Daemon, f func(client.APIClient, poll.LogT) poll.Result) func(poll.LogT) poll.Result {
- return func(pt poll.LogT) poll.Result {
- c := d.NewClientT(t)
- return f(c, pt)
- }
-}
diff --git a/internal/test/daemon/secret.go b/internal/test/daemon/secret.go
deleted file mode 100644
index f3db7a4260..0000000000
--- a/internal/test/daemon/secret.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package daemon
-
-import (
- "context"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-// SecretConstructor defines a swarm secret constructor
-type SecretConstructor func(*swarm.Secret)
-
-// CreateSecret creates a secret given the specified spec
-func (d *Daemon) CreateSecret(t assert.TestingT, secretSpec swarm.SecretSpec) string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- scr, err := cli.SecretCreate(context.Background(), secretSpec)
- assert.NilError(t, err)
-
- return scr.ID
-}
-
-// ListSecrets returns the list of the current swarm secrets
-func (d *Daemon) ListSecrets(t assert.TestingT) []swarm.Secret {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- secrets, err := cli.SecretList(context.Background(), types.SecretListOptions{})
- assert.NilError(t, err)
- return secrets
-}
-
-// GetSecret returns a swarm secret identified by the specified id
-func (d *Daemon) GetSecret(t assert.TestingT, id string) *swarm.Secret {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- secret, _, err := cli.SecretInspectWithRaw(context.Background(), id)
- assert.NilError(t, err)
- return &secret
-}
-
-// DeleteSecret removes the swarm secret identified by the specified id
-func (d *Daemon) DeleteSecret(t assert.TestingT, id string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- err := cli.SecretRemove(context.Background(), id)
- assert.NilError(t, err)
-}
-
-// UpdateSecret updates the swarm secret identified by the specified id
-// Currently, only label update is supported.
-func (d *Daemon) UpdateSecret(t assert.TestingT, id string, f ...SecretConstructor) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- secret := d.GetSecret(t, id)
- for _, fn := range f {
- fn(secret)
- }
-
- err := cli.SecretUpdate(context.Background(), secret.ID, secret.Version, secret.Spec)
-
- assert.NilError(t, err)
-}
diff --git a/internal/test/daemon/service.go b/internal/test/daemon/service.go
deleted file mode 100644
index a51671639c..0000000000
--- a/internal/test/daemon/service.go
+++ /dev/null
@@ -1,134 +0,0 @@
-package daemon
-
-import (
- "context"
- "time"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-// ServiceConstructor defines a swarm service constructor function
-type ServiceConstructor func(*swarm.Service)
-
-func (d *Daemon) createServiceWithOptions(t assert.TestingT, opts types.ServiceCreateOptions, f ...ServiceConstructor) string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- var service swarm.Service
- for _, fn := range f {
- fn(&service)
- }
-
- cli := d.NewClientT(t)
- defer cli.Close()
-
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
-
- res, err := cli.ServiceCreate(ctx, service.Spec, opts)
- assert.NilError(t, err)
- return res.ID
-}
-
-// CreateService creates a swarm service given the specified service constructor
-func (d *Daemon) CreateService(t assert.TestingT, f ...ServiceConstructor) string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- return d.createServiceWithOptions(t, types.ServiceCreateOptions{}, f...)
-}
-
-// GetService returns the swarm service corresponding to the specified id
-func (d *Daemon) GetService(t assert.TestingT, id string) *swarm.Service {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- service, _, err := cli.ServiceInspectWithRaw(context.Background(), id, types.ServiceInspectOptions{})
- assert.NilError(t, err)
- return &service
-}
-
-// GetServiceTasks returns the swarm tasks for the specified service
-func (d *Daemon) GetServiceTasks(t assert.TestingT, service string, additionalFilters ...filters.KeyValuePair) []swarm.Task {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- filterArgs := filters.NewArgs()
- filterArgs.Add("desired-state", "running")
- filterArgs.Add("service", service)
- for _, filter := range additionalFilters {
- filterArgs.Add(filter.Key, filter.Value)
- }
-
- options := types.TaskListOptions{
- Filters: filterArgs,
- }
-
- tasks, err := cli.TaskList(context.Background(), options)
- assert.NilError(t, err)
- return tasks
-}
-
-// UpdateService updates a swarm service with the specified service constructor
-func (d *Daemon) UpdateService(t assert.TestingT, service *swarm.Service, f ...ServiceConstructor) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- for _, fn := range f {
- fn(service)
- }
-
- _, err := cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
- assert.NilError(t, err)
-}
-
-// RemoveService removes the specified service
-func (d *Daemon) RemoveService(t assert.TestingT, id string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- err := cli.ServiceRemove(context.Background(), id)
- assert.NilError(t, err)
-}
-
-// ListServices returns the list of the current swarm services
-func (d *Daemon) ListServices(t assert.TestingT) []swarm.Service {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- services, err := cli.ServiceList(context.Background(), types.ServiceListOptions{})
- assert.NilError(t, err)
- return services
-}
-
-// GetTask returns the swarm task identified by the specified id
-func (d *Daemon) GetTask(t assert.TestingT, id string) swarm.Task {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- task, _, err := cli.TaskInspectWithRaw(context.Background(), id)
- assert.NilError(t, err)
- return task
-}
diff --git a/internal/test/daemon/swarm.go b/internal/test/daemon/swarm.go
deleted file mode 100644
index 20300a1f4a..0000000000
--- a/internal/test/daemon/swarm.go
+++ /dev/null
@@ -1,223 +0,0 @@
-package daemon
-
-import (
- "context"
- "fmt"
-
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/internal/test"
- "github.com/pkg/errors"
- "gotest.tools/assert"
-)
-
-const (
- // DefaultSwarmPort is the default port use for swarm in the tests
- DefaultSwarmPort = 2477
- defaultSwarmListenAddr = "0.0.0.0"
-)
-
-var (
- startArgs = []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
-)
-
-// StartNode (re)starts the daemon
-func (d *Daemon) StartNode(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- d.Start(t, startArgs...)
-}
-
-// StartNodeWithBusybox starts daemon to be used as a swarm node, and loads the busybox image
-func (d *Daemon) StartNodeWithBusybox(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- d.StartWithBusybox(t, startArgs...)
-}
-
-// RestartNode restarts a daemon to be used as a swarm node
-func (d *Daemon) RestartNode(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- // avoid networking conflicts
- d.Stop(t)
- d.Start(t, startArgs...)
-}
-
-// StartAndSwarmInit starts the daemon (with busybox) and init the swarm
-func (d *Daemon) StartAndSwarmInit(t testingT) {
- d.StartNodeWithBusybox(t)
- d.SwarmInit(t, swarm.InitRequest{})
-}
-
-// StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager
-func (d *Daemon) StartAndSwarmJoin(t testingT, leader *Daemon, manager bool) {
- if th, ok := t.(test.HelperT); ok {
- th.Helper()
- }
- d.StartNodeWithBusybox(t)
-
- tokens := leader.JoinTokens(t)
- token := tokens.Worker
- if manager {
- token = tokens.Manager
- }
- t.Logf("[%s] joining swarm manager [%s]@%s, swarm listen addr %s", d.id, leader.id, leader.SwarmListenAddr(), d.SwarmListenAddr())
- d.SwarmJoin(t, swarm.JoinRequest{
- RemoteAddrs: []string{leader.SwarmListenAddr()},
- JoinToken: token,
- })
-}
-
-// SpecConstructor defines a swarm spec constructor
-type SpecConstructor func(*swarm.Spec)
-
-// SwarmListenAddr returns the listen-addr used for the daemon
-func (d *Daemon) SwarmListenAddr() string {
- return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
-}
-
-// NodeID returns the swarm mode node ID
-func (d *Daemon) NodeID() string {
- return d.CachedInfo.Swarm.NodeID
-}
-
-// SwarmInit initializes a new swarm cluster.
-func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- if req.ListenAddr == "" {
- req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
- }
- if req.DefaultAddrPool == nil {
- req.DefaultAddrPool = d.DefaultAddrPool
- req.SubnetSize = d.SubnetSize
- }
- if d.DataPathPort > 0 {
- req.DataPathPort = d.DataPathPort
- }
- cli := d.NewClientT(t)
- defer cli.Close()
- _, err := cli.SwarmInit(context.Background(), req)
- assert.NilError(t, err, "initializing swarm")
- d.CachedInfo = d.Info(t)
-}
-
-// SwarmJoin joins a daemon to an existing cluster.
-func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- if req.ListenAddr == "" {
- req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
- }
- cli := d.NewClientT(t)
- defer cli.Close()
- err := cli.SwarmJoin(context.Background(), req)
- assert.NilError(t, err, "[%s] joining swarm", d.id)
- d.CachedInfo = d.Info(t)
-}
-
-// SwarmLeave forces daemon to leave current cluster.
-//
-// The passed in TestingT is only used to validate that the client was successfully created
-// Some tests rely on error checking the result of the actual unlock, so allow
-// the error to be returned.
-func (d *Daemon) SwarmLeave(t assert.TestingT, force bool) error {
- cli := d.NewClientT(t)
- defer cli.Close()
- return cli.SwarmLeave(context.Background(), force)
-}
-
-// SwarmInfo returns the swarm information of the daemon
-func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- info, err := cli.Info(context.Background())
- assert.NilError(t, err, "get swarm info")
- return info.Swarm
-}
-
-// SwarmUnlock tries to unlock a locked swarm
-//
-// The passed in TestingT is only used to validate that the client was successfully created
-// Some tests rely on error checking the result of the actual unlock, so allow
-// the error to be returned.
-func (d *Daemon) SwarmUnlock(t assert.TestingT, req swarm.UnlockRequest) error {
- cli := d.NewClientT(t)
- defer cli.Close()
-
- err := cli.SwarmUnlock(context.Background(), req)
- if err != nil {
- err = errors.Wrap(err, "unlocking swarm")
- }
- return err
-}
-
-// GetSwarm returns the current swarm object
-func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- sw, err := cli.SwarmInspect(context.Background())
- assert.NilError(t, err)
- return sw
-}
-
-// UpdateSwarm updates the current swarm object with the specified spec constructors
-func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- sw := d.GetSwarm(t)
- for _, fn := range f {
- fn(&sw.Spec)
- }
-
- err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
- assert.NilError(t, err)
-}
-
-// RotateTokens update the swarm to rotate tokens
-func (d *Daemon) RotateTokens(t assert.TestingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- sw, err := cli.SwarmInspect(context.Background())
- assert.NilError(t, err)
-
- flags := swarm.UpdateFlags{
- RotateManagerToken: true,
- RotateWorkerToken: true,
- }
-
- err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
- assert.NilError(t, err)
-}
-
-// JoinTokens returns the current swarm join tokens
-func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- cli := d.NewClientT(t)
- defer cli.Close()
-
- sw, err := cli.SwarmInspect(context.Background())
- assert.NilError(t, err)
- return sw.JoinTokens
-}
diff --git a/internal/test/environment/clean.go b/internal/test/environment/clean.go
deleted file mode 100644
index ad6ec93e4a..0000000000
--- a/internal/test/environment/clean.go
+++ /dev/null
@@ -1,207 +0,0 @@
-package environment // import "github.com/docker/docker/internal/test/environment"
-
-import (
- "context"
- "regexp"
- "strings"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/client"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-// Clean the environment, preserving protected objects (images, containers, ...)
-// and removing everything else. It's meant to run after any tests so that they don't
-// depend on each others.
-func (e *Execution) Clean(t assert.TestingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := e.APIClient()
-
- platform := e.OSType
- if (platform != "windows") || (platform == "windows" && e.DaemonInfo.Isolation == "hyperv") {
- unpauseAllContainers(t, client)
- }
- deleteAllContainers(t, client, e.protectedElements.containers)
- deleteAllImages(t, client, e.protectedElements.images)
- deleteAllVolumes(t, client, e.protectedElements.volumes)
- deleteAllNetworks(t, client, platform, e.protectedElements.networks)
- if platform == "linux" {
- deleteAllPlugins(t, client, e.protectedElements.plugins)
- }
-}
-
-func unpauseAllContainers(t assert.TestingT, client client.ContainerAPIClient) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- ctx := context.Background()
- containers := getPausedContainers(ctx, t, client)
- if len(containers) > 0 {
- for _, container := range containers {
- err := client.ContainerUnpause(ctx, container.ID)
- assert.Check(t, err, "failed to unpause container %s", container.ID)
- }
- }
-}
-
-func getPausedContainers(ctx context.Context, t assert.TestingT, client client.ContainerAPIClient) []types.Container {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- filter := filters.NewArgs()
- filter.Add("status", "paused")
- containers, err := client.ContainerList(ctx, types.ContainerListOptions{
- Filters: filter,
- Quiet: true,
- All: true,
- })
- assert.Check(t, err, "failed to list containers")
- return containers
-}
-
-var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`)
-
-func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient, protectedContainers map[string]struct{}) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- ctx := context.Background()
- containers := getAllContainers(ctx, t, apiclient)
- if len(containers) == 0 {
- return
- }
-
- for _, container := range containers {
- if _, ok := protectedContainers[container.ID]; ok {
- continue
- }
- err := apiclient.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{
- Force: true,
- RemoveVolumes: true,
- })
- if err == nil || client.IsErrNotFound(err) || alreadyExists.MatchString(err.Error()) || isErrNotFoundSwarmClassic(err) {
- continue
- }
- assert.Check(t, err, "failed to remove %s", container.ID)
- }
-}
-
-func getAllContainers(ctx context.Context, t assert.TestingT, client client.ContainerAPIClient) []types.Container {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- containers, err := client.ContainerList(ctx, types.ContainerListOptions{
- Quiet: true,
- All: true,
- })
- assert.Check(t, err, "failed to list containers")
- return containers
-}
-
-func deleteAllImages(t assert.TestingT, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{})
- assert.Check(t, err, "failed to list images")
-
- ctx := context.Background()
- for _, image := range images {
- tags := tagsFromImageSummary(image)
- if len(tags) == 0 {
- removeImage(ctx, t, apiclient, image.ID)
- continue
- }
- for _, tag := range tags {
- if _, ok := protectedImages[tag]; !ok {
- removeImage(ctx, t, apiclient, tag)
- }
- }
- }
-}
-
-func removeImage(ctx context.Context, t assert.TestingT, apiclient client.ImageAPIClient, ref string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- _, err := apiclient.ImageRemove(ctx, ref, types.ImageRemoveOptions{
- Force: true,
- })
- if client.IsErrNotFound(err) {
- return
- }
- assert.Check(t, err, "failed to remove image %s", ref)
-}
-
-func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- volumes, err := c.VolumeList(context.Background(), filters.Args{})
- assert.Check(t, err, "failed to list volumes")
-
- for _, v := range volumes.Volumes {
- if _, ok := protectedVolumes[v.Name]; ok {
- continue
- }
- err := c.VolumeRemove(context.Background(), v.Name, true)
- // Docker EE may list volumes that no longer exist.
- if isErrNotFoundSwarmClassic(err) {
- continue
- }
- assert.Check(t, err, "failed to remove volume %s", v.Name)
- }
-}
-
-func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{})
- assert.Check(t, err, "failed to list networks")
-
- for _, n := range networks {
- if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
- continue
- }
- if _, ok := protectedNetworks[n.ID]; ok {
- continue
- }
- if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
- // nat is a pre-defined network on Windows and cannot be removed
- continue
- }
- err := c.NetworkRemove(context.Background(), n.ID)
- assert.Check(t, err, "failed to remove network %s", n.ID)
- }
-}
-
-func deleteAllPlugins(t assert.TestingT, c client.PluginAPIClient, protectedPlugins map[string]struct{}) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- plugins, err := c.PluginList(context.Background(), filters.Args{})
- // Docker EE does not allow cluster-wide plugin management.
- if client.IsErrNotImplemented(err) {
- return
- }
- assert.Check(t, err, "failed to list plugins")
-
- for _, p := range plugins {
- if _, ok := protectedPlugins[p.Name]; ok {
- continue
- }
- err := c.PluginRemove(context.Background(), p.Name, types.PluginRemoveOptions{Force: true})
- assert.Check(t, err, "failed to remove plugin %s", p.ID)
- }
-}
-
-// Swarm classic aggregates node errors and returns a 500 so we need to check
-// the error string instead of just IsErrNotFound().
-func isErrNotFoundSwarmClassic(err error) bool {
- return err != nil && strings.Contains(strings.ToLower(err.Error()), "no such")
-}
diff --git a/internal/test/environment/environment.go b/internal/test/environment/environment.go
deleted file mode 100644
index 3310590e7c..0000000000
--- a/internal/test/environment/environment.go
+++ /dev/null
@@ -1,195 +0,0 @@
-package environment // import "github.com/docker/docker/internal/test/environment"
-
-import (
- "context"
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/client"
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/internal/test/fixtures/load"
- "github.com/pkg/errors"
- "gotest.tools/assert"
-)
-
-// Execution contains information about the current test execution and daemon
-// under test
-type Execution struct {
- client client.APIClient
- DaemonInfo types.Info
- OSType string
- PlatformDefaults PlatformDefaults
- protectedElements protectedElements
-}
-
-// PlatformDefaults are defaults values for the platform of the daemon under test
-type PlatformDefaults struct {
- BaseImage string
- VolumesConfigPath string
- ContainerStoragePath string
-}
-
-// New creates a new Execution struct
-// This is configured useing the env client (see client.FromEnv)
-func New() (*Execution, error) {
- c, err := client.NewClientWithOpts(client.FromEnv)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to create client")
- }
- return FromClient(c)
-}
-
-// FromClient creates a new Execution environment from the passed in client
-func FromClient(c *client.Client) (*Execution, error) {
- info, err := c.Info(context.Background())
- if err != nil {
- return nil, errors.Wrapf(err, "failed to get info from daemon")
- }
-
- osType := getOSType(info)
-
- return &Execution{
- client: c,
- DaemonInfo: info,
- OSType: osType,
- PlatformDefaults: getPlatformDefaults(info, osType),
- protectedElements: newProtectedElements(),
- }, nil
-}
-
-func getOSType(info types.Info) string {
- // Docker EE does not set the OSType so allow the user to override this value.
- userOsType := os.Getenv("TEST_OSTYPE")
- if userOsType != "" {
- return userOsType
- }
- return info.OSType
-}
-
-func getPlatformDefaults(info types.Info, osType string) PlatformDefaults {
- volumesPath := filepath.Join(info.DockerRootDir, "volumes")
- containersPath := filepath.Join(info.DockerRootDir, "containers")
-
- switch osType {
- case "linux":
- return PlatformDefaults{
- BaseImage: "scratch",
- VolumesConfigPath: toSlash(volumesPath),
- ContainerStoragePath: toSlash(containersPath),
- }
- case "windows":
- baseImage := "microsoft/windowsservercore"
- if overrideBaseImage := os.Getenv("WINDOWS_BASE_IMAGE"); overrideBaseImage != "" {
- baseImage = overrideBaseImage
- if overrideBaseImageTag := os.Getenv("WINDOWS_BASE_IMAGE_TAG"); overrideBaseImageTag != "" {
- baseImage = baseImage + ":" + overrideBaseImageTag
- }
- }
- fmt.Println("INFO: Windows Base image is ", baseImage)
- return PlatformDefaults{
- BaseImage: baseImage,
- VolumesConfigPath: filepath.FromSlash(volumesPath),
- ContainerStoragePath: filepath.FromSlash(containersPath),
- }
- default:
- panic(fmt.Sprintf("unknown OSType for daemon: %s", osType))
- }
-}
-
-// Make sure in context of daemon, not the local platform. Note we can't
-// use filepath.FromSlash or ToSlash here as they are a no-op on Unix.
-func toSlash(path string) string {
- return strings.Replace(path, `\`, `/`, -1)
-}
-
-// IsLocalDaemon is true if the daemon under test is on the same
-// host as the test process.
-//
-// Deterministically working out the environment in which CI is running
-// to evaluate whether the daemon is local or remote is not possible through
-// a build tag.
-//
-// For example Windows to Linux CI under Jenkins tests the 64-bit
-// Windows binary build with the daemon build tag, but calls a remote
-// Linux daemon.
-//
-// We can't just say if Windows then assume the daemon is local as at
-// some point, we will be testing the Windows CLI against a Windows daemon.
-//
-// Similarly, it will be perfectly valid to also run CLI tests from
-// a Linux CLI (built with the daemon tag) against a Windows daemon.
-func (e *Execution) IsLocalDaemon() bool {
- return os.Getenv("DOCKER_REMOTE_DAEMON") == ""
-}
-
-// IsRemoteDaemon is true if the daemon under test is on different host
-// as the test process.
-func (e *Execution) IsRemoteDaemon() bool {
- return !e.IsLocalDaemon()
-}
-
-// DaemonAPIVersion returns the negotiated daemon api version
-func (e *Execution) DaemonAPIVersion() string {
- version, err := e.APIClient().ServerVersion(context.TODO())
- if err != nil {
- return ""
- }
- return version.APIVersion
-}
-
-// Print the execution details to stdout
-// TODO: print everything
-func (e *Execution) Print() {
- if e.IsLocalDaemon() {
- fmt.Println("INFO: Testing against a local daemon")
- } else {
- fmt.Println("INFO: Testing against a remote daemon")
- }
-}
-
-// APIClient returns an APIClient connected to the daemon under test
-func (e *Execution) APIClient() client.APIClient {
- return e.client
-}
-
-// IsUserNamespace returns whether the user namespace remapping is enabled
-func (e *Execution) IsUserNamespace() bool {
- root := os.Getenv("DOCKER_REMAP_ROOT")
- return root != ""
-}
-
-// HasExistingImage checks whether there is an image with the given reference.
-// Note that this is done by filtering and then checking whether there were any
-// results -- so ambiguous references might result in false-positives.
-func (e *Execution) HasExistingImage(t assert.TestingT, reference string) bool {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := e.APIClient()
- filter := filters.NewArgs()
- filter.Add("dangling", "false")
- filter.Add("reference", reference)
- imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
- All: true,
- Filters: filter,
- })
- assert.NilError(t, err, "failed to list images")
-
- return len(imageList) > 0
-}
-
-// EnsureFrozenImagesLinux loads frozen test images into the daemon
-// if they aren't already loaded
-func EnsureFrozenImagesLinux(testEnv *Execution) error {
- if testEnv.OSType == "linux" {
- err := load.FrozenImagesLinux(testEnv.APIClient(), frozenImages...)
- if err != nil {
- return errors.Wrap(err, "error loading frozen images")
- }
- }
- return nil
-}
diff --git a/internal/test/environment/protect.go b/internal/test/environment/protect.go
deleted file mode 100644
index a47ea3c2fd..0000000000
--- a/internal/test/environment/protect.go
+++ /dev/null
@@ -1,254 +0,0 @@
-package environment // import "github.com/docker/docker/internal/test/environment"
-
-import (
- "context"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/filters"
- dclient "github.com/docker/docker/client"
- "github.com/docker/docker/internal/test"
- "gotest.tools/assert"
-)
-
-var frozenImages = []string{"busybox:latest", "busybox:glibc", "hello-world:frozen", "debian:jessie"}
-
-type protectedElements struct {
- containers map[string]struct{}
- images map[string]struct{}
- networks map[string]struct{}
- plugins map[string]struct{}
- volumes map[string]struct{}
-}
-
-func newProtectedElements() protectedElements {
- return protectedElements{
- containers: map[string]struct{}{},
- images: map[string]struct{}{},
- networks: map[string]struct{}{},
- plugins: map[string]struct{}{},
- volumes: map[string]struct{}{},
- }
-}
-
-// ProtectAll protects the existing environment (containers, images, networks,
-// volumes, and, on Linux, plugins) from being cleaned up at the end of test
-// runs
-func ProtectAll(t assert.TestingT, testEnv *Execution) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- ProtectContainers(t, testEnv)
- ProtectImages(t, testEnv)
- ProtectNetworks(t, testEnv)
- ProtectVolumes(t, testEnv)
- if testEnv.OSType == "linux" {
- ProtectPlugins(t, testEnv)
- }
-}
-
-// ProtectContainer adds the specified container(s) to be protected in case of
-// clean
-func (e *Execution) ProtectContainer(t assert.TestingT, containers ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- for _, container := range containers {
- e.protectedElements.containers[container] = struct{}{}
- }
-}
-
-// ProtectContainers protects existing containers from being cleaned up at the
-// end of test runs
-func ProtectContainers(t assert.TestingT, testEnv *Execution) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- containers := getExistingContainers(t, testEnv)
- testEnv.ProtectContainer(t, containers...)
-}
-
-func getExistingContainers(t assert.TestingT, testEnv *Execution) []string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := testEnv.APIClient()
- containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{
- All: true,
- })
- assert.NilError(t, err, "failed to list containers")
-
- var containers []string
- for _, container := range containerList {
- containers = append(containers, container.ID)
- }
- return containers
-}
-
-// ProtectImage adds the specified image(s) to be protected in case of clean
-func (e *Execution) ProtectImage(t assert.TestingT, images ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- for _, image := range images {
- e.protectedElements.images[image] = struct{}{}
- }
-}
-
-// ProtectImages protects existing images and on linux frozen images from being
-// cleaned up at the end of test runs
-func ProtectImages(t assert.TestingT, testEnv *Execution) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- images := getExistingImages(t, testEnv)
-
- if testEnv.OSType == "linux" {
- images = append(images, frozenImages...)
- }
- testEnv.ProtectImage(t, images...)
-}
-
-func getExistingImages(t assert.TestingT, testEnv *Execution) []string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := testEnv.APIClient()
- filter := filters.NewArgs()
- filter.Add("dangling", "false")
- imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
- All: true,
- Filters: filter,
- })
- assert.NilError(t, err, "failed to list images")
-
- var images []string
- for _, image := range imageList {
- images = append(images, tagsFromImageSummary(image)...)
- }
- return images
-}
-
-func tagsFromImageSummary(image types.ImageSummary) []string {
- var result []string
- for _, tag := range image.RepoTags {
- if tag != "<none>:<none>" {
- result = append(result, tag)
- }
- }
- for _, digest := range image.RepoDigests {
- if digest != "<none>@<none>" {
- result = append(result, digest)
- }
- }
- return result
-}
-
-// ProtectNetwork adds the specified network(s) to be protected in case of
-// clean
-func (e *Execution) ProtectNetwork(t assert.TestingT, networks ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- for _, network := range networks {
- e.protectedElements.networks[network] = struct{}{}
- }
-}
-
-// ProtectNetworks protects existing networks from being cleaned up at the end
-// of test runs
-func ProtectNetworks(t assert.TestingT, testEnv *Execution) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- networks := getExistingNetworks(t, testEnv)
- testEnv.ProtectNetwork(t, networks...)
-}
-
-func getExistingNetworks(t assert.TestingT, testEnv *Execution) []string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := testEnv.APIClient()
- networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{})
- assert.NilError(t, err, "failed to list networks")
-
- var networks []string
- for _, network := range networkList {
- networks = append(networks, network.ID)
- }
- return networks
-}
-
-// ProtectPlugin adds the specified plugin(s) to be protected in case of clean
-func (e *Execution) ProtectPlugin(t assert.TestingT, plugins ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- for _, plugin := range plugins {
- e.protectedElements.plugins[plugin] = struct{}{}
- }
-}
-
-// ProtectPlugins protects existing plugins from being cleaned up at the end of
-// test runs
-func ProtectPlugins(t assert.TestingT, testEnv *Execution) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- plugins := getExistingPlugins(t, testEnv)
- testEnv.ProtectPlugin(t, plugins...)
-}
-
-func getExistingPlugins(t assert.TestingT, testEnv *Execution) []string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := testEnv.APIClient()
- pluginList, err := client.PluginList(context.Background(), filters.Args{})
- // Docker EE does not allow cluster-wide plugin management.
- if dclient.IsErrNotImplemented(err) {
- return []string{}
- }
- assert.NilError(t, err, "failed to list plugins")
-
- var plugins []string
- for _, plugin := range pluginList {
- plugins = append(plugins, plugin.Name)
- }
- return plugins
-}
-
-// ProtectVolume adds the specified volume(s) to be protected in case of clean
-func (e *Execution) ProtectVolume(t assert.TestingT, volumes ...string) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- for _, volume := range volumes {
- e.protectedElements.volumes[volume] = struct{}{}
- }
-}
-
-// ProtectVolumes protects existing volumes from being cleaned up at the end of
-// test runs
-func ProtectVolumes(t assert.TestingT, testEnv *Execution) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- volumes := getExistingVolumes(t, testEnv)
- testEnv.ProtectVolume(t, volumes...)
-}
-
-func getExistingVolumes(t assert.TestingT, testEnv *Execution) []string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- client := testEnv.APIClient()
- volumeList, err := client.VolumeList(context.Background(), filters.Args{})
- assert.NilError(t, err, "failed to list volumes")
-
- var volumes []string
- for _, volume := range volumeList.Volumes {
- volumes = append(volumes, volume.Name)
- }
- return volumes
-}
diff --git a/internal/test/fakecontext/context.go b/internal/test/fakecontext/context.go
deleted file mode 100644
index 8b11da207e..0000000000
--- a/internal/test/fakecontext/context.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package fakecontext // import "github.com/docker/docker/internal/test/fakecontext"
-
-import (
- "bytes"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
-
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/pkg/archive"
-)
-
-type testingT interface {
- Fatal(args ...interface{})
- Fatalf(string, ...interface{})
-}
-
-// New creates a fake build context
-func New(t testingT, dir string, modifiers ...func(*Fake) error) *Fake {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- fakeContext := &Fake{Dir: dir}
- if dir == "" {
- if err := newDir(fakeContext); err != nil {
- t.Fatal(err)
- }
- }
-
- for _, modifier := range modifiers {
- if err := modifier(fakeContext); err != nil {
- t.Fatal(err)
- }
- }
-
- return fakeContext
-}
-
-func newDir(fake *Fake) error {
- tmp, err := ioutil.TempDir("", "fake-context")
- if err != nil {
- return err
- }
- if err := os.Chmod(tmp, 0755); err != nil {
- return err
- }
- fake.Dir = tmp
- return nil
-}
-
-// WithFile adds the specified file (with content) in the build context
-func WithFile(name, content string) func(*Fake) error {
- return func(ctx *Fake) error {
- return ctx.Add(name, content)
- }
-}
-
-// WithDockerfile adds the specified content as Dockerfile in the build context
-func WithDockerfile(content string) func(*Fake) error {
- return WithFile("Dockerfile", content)
-}
-
-// WithFiles adds the specified files in the build context, content is a string
-func WithFiles(files map[string]string) func(*Fake) error {
- return func(fakeContext *Fake) error {
- for file, content := range files {
- if err := fakeContext.Add(file, content); err != nil {
- return err
- }
- }
- return nil
- }
-}
-
-// WithBinaryFiles adds the specified files in the build context, content is binary
-func WithBinaryFiles(files map[string]*bytes.Buffer) func(*Fake) error {
- return func(fakeContext *Fake) error {
- for file, content := range files {
- if err := fakeContext.Add(file, content.String()); err != nil {
- return err
- }
- }
- return nil
- }
-}
-
-// Fake creates directories that can be used as a build context
-type Fake struct {
- Dir string
-}
-
-// Add a file at a path, creating directories where necessary
-func (f *Fake) Add(file, content string) error {
- return f.addFile(file, []byte(content))
-}
-
-func (f *Fake) addFile(file string, content []byte) error {
- fp := filepath.Join(f.Dir, filepath.FromSlash(file))
- dirpath := filepath.Dir(fp)
- if dirpath != "." {
- if err := os.MkdirAll(dirpath, 0755); err != nil {
- return err
- }
- }
- return ioutil.WriteFile(fp, content, 0644)
-
-}
-
-// Delete a file at a path
-func (f *Fake) Delete(file string) error {
- fp := filepath.Join(f.Dir, filepath.FromSlash(file))
- return os.RemoveAll(fp)
-}
-
-// Close deletes the context
-func (f *Fake) Close() error {
- return os.RemoveAll(f.Dir)
-}
-
-// AsTarReader returns a ReadCloser with the contents of Dir as a tar archive.
-func (f *Fake) AsTarReader(t testingT) io.ReadCloser {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- reader, err := archive.TarWithOptions(f.Dir, &archive.TarOptions{})
- if err != nil {
- t.Fatalf("Failed to create tar from %s: %s", f.Dir, err)
- }
- return reader
-}
diff --git a/internal/test/fakegit/fakegit.go b/internal/test/fakegit/fakegit.go
deleted file mode 100644
index 30de769743..0000000000
--- a/internal/test/fakegit/fakegit.go
+++ /dev/null
@@ -1,136 +0,0 @@
-package fakegit // import "github.com/docker/docker/internal/test/fakegit"
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "os"
- "os/exec"
- "path/filepath"
-
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/internal/test/fakecontext"
- "github.com/docker/docker/internal/test/fakestorage"
- "gotest.tools/assert"
-)
-
-type testingT interface {
- assert.TestingT
- logT
- skipT
- Fatal(args ...interface{})
- Fatalf(string, ...interface{})
-}
-
-type logT interface {
- Logf(string, ...interface{})
-}
-
-type skipT interface {
- Skip(...interface{})
-}
-
-type gitServer interface {
- URL() string
- Close() error
-}
-
-type localGitServer struct {
- *httptest.Server
-}
-
-func (r *localGitServer) Close() error {
- r.Server.Close()
- return nil
-}
-
-func (r *localGitServer) URL() string {
- return r.Server.URL
-}
-
-// FakeGit is a fake git server
-type FakeGit struct {
- root string
- server gitServer
- RepoURL string
-}
-
-// Close closes the server, implements Closer interface
-func (g *FakeGit) Close() {
- g.server.Close()
- os.RemoveAll(g.root)
-}
-
-// New create a fake git server that can be used for git related tests
-func New(c testingT, name string, files map[string]string, enforceLocalServer bool) *FakeGit {
- if ht, ok := c.(test.HelperT); ok {
- ht.Helper()
- }
- ctx := fakecontext.New(c, "", fakecontext.WithFiles(files))
- defer ctx.Close()
- curdir, err := os.Getwd()
- if err != nil {
- c.Fatal(err)
- }
- defer os.Chdir(curdir)
-
- if output, err := exec.Command("git", "init", ctx.Dir).CombinedOutput(); err != nil {
- c.Fatalf("error trying to init repo: %s (%s)", err, output)
- }
- err = os.Chdir(ctx.Dir)
- if err != nil {
- c.Fatal(err)
- }
- if output, err := exec.Command("git", "config", "user.name", "Fake User").CombinedOutput(); err != nil {
- c.Fatalf("error trying to set 'user.name': %s (%s)", err, output)
- }
- if output, err := exec.Command("git", "config", "user.email", "fake.user@example.com").CombinedOutput(); err != nil {
- c.Fatalf("error trying to set 'user.email': %s (%s)", err, output)
- }
- if output, err := exec.Command("git", "add", "*").CombinedOutput(); err != nil {
- c.Fatalf("error trying to add files to repo: %s (%s)", err, output)
- }
- if output, err := exec.Command("git", "commit", "-a", "-m", "Initial commit").CombinedOutput(); err != nil {
- c.Fatalf("error trying to commit to repo: %s (%s)", err, output)
- }
-
- root, err := ioutil.TempDir("", "docker-test-git-repo")
- if err != nil {
- c.Fatal(err)
- }
- repoPath := filepath.Join(root, name+".git")
- if output, err := exec.Command("git", "clone", "--bare", ctx.Dir, repoPath).CombinedOutput(); err != nil {
- os.RemoveAll(root)
- c.Fatalf("error trying to clone --bare: %s (%s)", err, output)
- }
- err = os.Chdir(repoPath)
- if err != nil {
- os.RemoveAll(root)
- c.Fatal(err)
- }
- if output, err := exec.Command("git", "update-server-info").CombinedOutput(); err != nil {
- os.RemoveAll(root)
- c.Fatalf("error trying to git update-server-info: %s (%s)", err, output)
- }
- err = os.Chdir(curdir)
- if err != nil {
- os.RemoveAll(root)
- c.Fatal(err)
- }
-
- var server gitServer
- if !enforceLocalServer {
- // use fakeStorage server, which might be local or remote (at test daemon)
- server = fakestorage.New(c, root)
- } else {
- // always start a local http server on CLI test machine
- httpServer := httptest.NewServer(http.FileServer(http.Dir(root)))
- server = &localGitServer{httpServer}
- }
- return &FakeGit{
- root: root,
- server: server,
- RepoURL: fmt.Sprintf("%s/%s.git", server.URL(), name),
- }
-}
diff --git a/internal/test/fakestorage/fixtures.go b/internal/test/fakestorage/fixtures.go
deleted file mode 100644
index ad8f763143..0000000000
--- a/internal/test/fakestorage/fixtures.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package fakestorage // import "github.com/docker/docker/internal/test/fakestorage"
-
-import (
- "context"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "sync"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/pkg/archive"
- "gotest.tools/assert"
-)
-
-var ensureHTTPServerOnce sync.Once
-
-func ensureHTTPServerImage(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- var doIt bool
- ensureHTTPServerOnce.Do(func() {
- doIt = true
- })
-
- if !doIt {
- return
- }
-
- defer testEnv.ProtectImage(t, "httpserver:latest")
-
- tmp, err := ioutil.TempDir("", "docker-http-server-test")
- if err != nil {
- t.Fatalf("could not build http server: %v", err)
- }
- defer os.RemoveAll(tmp)
-
- goos := testEnv.OSType
- if goos == "" {
- goos = "linux"
- }
- goarch := os.Getenv("DOCKER_ENGINE_GOARCH")
- if goarch == "" {
- goarch = "amd64"
- }
-
- cpCmd, lookErr := exec.LookPath("cp")
- if lookErr != nil {
- t.Fatalf("could not build http server: %v", lookErr)
- }
-
- if _, err = os.Stat("../contrib/httpserver/httpserver"); os.IsNotExist(err) {
- goCmd, lookErr := exec.LookPath("go")
- if lookErr != nil {
- t.Fatalf("could not build http server: %v", lookErr)
- }
-
- cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
- cmd.Env = append(os.Environ(), []string{
- "CGO_ENABLED=0",
- "GOOS=" + goos,
- "GOARCH=" + goarch,
- }...)
- var out []byte
- if out, err = cmd.CombinedOutput(); err != nil {
- t.Fatalf("could not build http server: %s", string(out))
- }
- } else {
- if out, err := exec.Command(cpCmd, "../contrib/httpserver/httpserver", filepath.Join(tmp, "httpserver")).CombinedOutput(); err != nil {
- t.Fatalf("could not copy http server: %v", string(out))
- }
- }
-
- if out, err := exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil {
- t.Fatalf("could not build http server: %v", string(out))
- }
-
- c := testEnv.APIClient()
- reader, err := archive.TarWithOptions(tmp, &archive.TarOptions{})
- assert.NilError(t, err)
- resp, err := c.ImageBuild(context.Background(), reader, types.ImageBuildOptions{
- Remove: true,
- ForceRemove: true,
- Tags: []string{"httpserver"},
- })
- assert.NilError(t, err)
- _, err = io.Copy(ioutil.Discard, resp.Body)
- assert.NilError(t, err)
-}
diff --git a/internal/test/fakestorage/storage.go b/internal/test/fakestorage/storage.go
deleted file mode 100644
index e229fd0813..0000000000
--- a/internal/test/fakestorage/storage.go
+++ /dev/null
@@ -1,200 +0,0 @@
-package fakestorage // import "github.com/docker/docker/internal/test/fakestorage"
-
-import (
- "context"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "net/url"
- "os"
- "strings"
-
- "github.com/docker/docker/api/types"
- containertypes "github.com/docker/docker/api/types/container"
- "github.com/docker/docker/client"
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/internal/test/environment"
- "github.com/docker/docker/internal/test/fakecontext"
- "github.com/docker/docker/internal/test/request"
- "github.com/docker/docker/internal/testutil"
- "github.com/docker/go-connections/nat"
- "gotest.tools/assert"
-)
-
-var testEnv *environment.Execution
-
-type testingT interface {
- assert.TestingT
- logT
- skipT
- Fatal(args ...interface{})
- Fatalf(string, ...interface{})
-}
-
-type logT interface {
- Logf(string, ...interface{})
-}
-
-type skipT interface {
- Skip(...interface{})
-}
-
-// Fake is a static file server. It might be running locally or remotely
-// on test host.
-type Fake interface {
- Close() error
- URL() string
- CtxDir() string
-}
-
-// SetTestEnvironment sets a static test environment
-// TODO: decouple this package from environment
-func SetTestEnvironment(env *environment.Execution) {
- testEnv = env
-}
-
-// New returns a static file server that will be use as build context.
-func New(t testingT, dir string, modifiers ...func(*fakecontext.Fake) error) Fake {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- if testEnv == nil {
- t.Fatal("fakstorage package requires SetTestEnvironment() to be called before use.")
- }
- ctx := fakecontext.New(t, dir, modifiers...)
- switch {
- case testEnv.IsRemoteDaemon() && strings.HasPrefix(request.DaemonHost(), "unix:///"):
- t.Skip("e2e run : daemon is remote but docker host points to a unix socket")
- case testEnv.IsLocalDaemon():
- return newLocalFakeStorage(ctx)
- default:
- return newRemoteFileServer(t, ctx, testEnv.APIClient())
- }
- return nil
-}
-
-// localFileStorage is a file storage on the running machine
-type localFileStorage struct {
- *fakecontext.Fake
- *httptest.Server
-}
-
-func (s *localFileStorage) URL() string {
- return s.Server.URL
-}
-
-func (s *localFileStorage) CtxDir() string {
- return s.Fake.Dir
-}
-
-func (s *localFileStorage) Close() error {
- defer s.Server.Close()
- return s.Fake.Close()
-}
-
-func newLocalFakeStorage(ctx *fakecontext.Fake) *localFileStorage {
- handler := http.FileServer(http.Dir(ctx.Dir))
- server := httptest.NewServer(handler)
- return &localFileStorage{
- Fake: ctx,
- Server: server,
- }
-}
-
-// remoteFileServer is a containerized static file server started on the remote
-// testing machine to be used in URL-accepting docker build functionality.
-type remoteFileServer struct {
- host string // hostname/port web server is listening to on docker host e.g. 0.0.0.0:43712
- container string
- image string
- client client.APIClient
- ctx *fakecontext.Fake
-}
-
-func (f *remoteFileServer) URL() string {
- u := url.URL{
- Scheme: "http",
- Host: f.host}
- return u.String()
-}
-
-func (f *remoteFileServer) CtxDir() string {
- return f.ctx.Dir
-}
-
-func (f *remoteFileServer) Close() error {
- defer func() {
- if f.ctx != nil {
- f.ctx.Close()
- }
- if f.image != "" {
- if _, err := f.client.ImageRemove(context.Background(), f.image, types.ImageRemoveOptions{
- Force: true,
- }); err != nil {
- fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err)
- }
- }
- if err := f.client.Close(); err != nil {
- fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err)
- }
- }()
- if f.container == "" {
- return nil
- }
- return f.client.ContainerRemove(context.Background(), f.container, types.ContainerRemoveOptions{
- Force: true,
- RemoveVolumes: true,
- })
-}
-
-func newRemoteFileServer(t testingT, ctx *fakecontext.Fake, c client.APIClient) *remoteFileServer {
- var (
- image = fmt.Sprintf("fileserver-img-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10)))
- container = fmt.Sprintf("fileserver-cnt-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10)))
- )
-
- ensureHTTPServerImage(t)
-
- // Build the image
- if err := ctx.Add("Dockerfile", `FROM httpserver
-COPY . /static`); err != nil {
- t.Fatal(err)
- }
- resp, err := c.ImageBuild(context.Background(), ctx.AsTarReader(t), types.ImageBuildOptions{
- NoCache: true,
- Tags: []string{image},
- })
- assert.NilError(t, err)
- _, err = io.Copy(ioutil.Discard, resp.Body)
- assert.NilError(t, err)
-
- // Start the container
- b, err := c.ContainerCreate(context.Background(), &containertypes.Config{
- Image: image,
- }, &containertypes.HostConfig{}, nil, container)
- assert.NilError(t, err)
- err = c.ContainerStart(context.Background(), b.ID, types.ContainerStartOptions{})
- assert.NilError(t, err)
-
- // Find out the system assigned port
- i, err := c.ContainerInspect(context.Background(), b.ID)
- assert.NilError(t, err)
- newP, err := nat.NewPort("tcp", "80")
- assert.NilError(t, err)
- ports, exists := i.NetworkSettings.Ports[newP]
- if !exists || len(ports) != 1 {
- t.Fatalf("unable to find port 80/tcp for %s", container)
- }
- host := ports[0].HostIP
- port := ports[0].HostPort
-
- return &remoteFileServer{
- container: container,
- image: image,
- host: fmt.Sprintf("%s:%s", host, port),
- ctx: ctx,
- client: c,
- }
-}
diff --git a/internal/test/fixtures/load/frozen.go b/internal/test/fixtures/load/frozen.go
deleted file mode 100644
index 94f3680f95..0000000000
--- a/internal/test/fixtures/load/frozen.go
+++ /dev/null
@@ -1,196 +0,0 @@
-package load // import "github.com/docker/docker/internal/test/fixtures/load"
-
-import (
- "bufio"
- "bytes"
- "context"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
- "sync"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/client"
- "github.com/docker/docker/pkg/jsonmessage"
- "github.com/docker/docker/pkg/term"
- "github.com/pkg/errors"
-)
-
-const frozenImgDir = "/docker-frozen-images"
-
-// FrozenImagesLinux loads the frozen image set for the integration suite
-// If the images are not available locally it will download them
-// TODO: This loads whatever is in the frozen image dir, regardless of what
-// images were passed in. If the images need to be downloaded, then it will respect
-// the passed in images
-func FrozenImagesLinux(client client.APIClient, images ...string) error {
- var loadImages []struct{ srcName, destName string }
- for _, img := range images {
- if !imageExists(client, img) {
- srcName := img
- // hello-world:latest gets re-tagged as hello-world:frozen
- // there are some tests that use hello-world:latest specifically so it pulls
- // the image and hello-world:frozen is used for when we just want a super
- // small image
- if img == "hello-world:frozen" {
- srcName = "hello-world:latest"
- }
- loadImages = append(loadImages, struct{ srcName, destName string }{
- srcName: srcName,
- destName: img,
- })
- }
- }
- if len(loadImages) == 0 {
- // everything is loaded, we're done
- return nil
- }
-
- ctx := context.Background()
- fi, err := os.Stat(frozenImgDir)
- if err != nil || !fi.IsDir() {
- srcImages := make([]string, 0, len(loadImages))
- for _, img := range loadImages {
- srcImages = append(srcImages, img.srcName)
- }
- if err := pullImages(ctx, client, srcImages); err != nil {
- return errors.Wrap(err, "error pulling image list")
- }
- } else {
- if err := loadFrozenImages(ctx, client); err != nil {
- return err
- }
- }
-
- for _, img := range loadImages {
- if img.srcName != img.destName {
- if err := client.ImageTag(ctx, img.srcName, img.destName); err != nil {
- return errors.Wrapf(err, "failed to tag %s as %s", img.srcName, img.destName)
- }
- if _, err := client.ImageRemove(ctx, img.srcName, types.ImageRemoveOptions{}); err != nil {
- return errors.Wrapf(err, "failed to remove %s", img.srcName)
- }
- }
- }
- return nil
-}
-
-func imageExists(client client.APIClient, name string) bool {
- _, _, err := client.ImageInspectWithRaw(context.Background(), name)
- return err == nil
-}
-
-func loadFrozenImages(ctx context.Context, client client.APIClient) error {
- tar, err := exec.LookPath("tar")
- if err != nil {
- return errors.Wrap(err, "could not find tar binary")
- }
- tarCmd := exec.Command(tar, "-cC", frozenImgDir, ".")
- out, err := tarCmd.StdoutPipe()
- if err != nil {
- return errors.Wrap(err, "error getting stdout pipe for tar command")
- }
-
- errBuf := bytes.NewBuffer(nil)
- tarCmd.Stderr = errBuf
- tarCmd.Start()
- defer tarCmd.Wait()
-
- resp, err := client.ImageLoad(ctx, out, true)
- if err != nil {
- return errors.Wrap(err, "failed to load frozen images")
- }
- defer resp.Body.Close()
- fd, isTerminal := term.GetFdInfo(os.Stdout)
- return jsonmessage.DisplayJSONMessagesStream(resp.Body, os.Stdout, fd, isTerminal, nil)
-}
-
-func pullImages(ctx context.Context, client client.APIClient, images []string) error {
- cwd, err := os.Getwd()
- if err != nil {
- return errors.Wrap(err, "error getting path to dockerfile")
- }
- dockerfile := os.Getenv("DOCKERFILE")
- if dockerfile == "" {
- dockerfile = "Dockerfile"
- }
- dockerfilePath := filepath.Join(filepath.Dir(filepath.Clean(cwd)), dockerfile)
- pullRefs, err := readFrozenImageList(dockerfilePath, images)
- if err != nil {
- return errors.Wrap(err, "error reading frozen image list")
- }
-
- var wg sync.WaitGroup
- chErr := make(chan error, len(images))
- for tag, ref := range pullRefs {
- wg.Add(1)
- go func(tag, ref string) {
- defer wg.Done()
- if err := pullTagAndRemove(ctx, client, ref, tag); err != nil {
- chErr <- err
- return
- }
- }(tag, ref)
- }
- wg.Wait()
- close(chErr)
- return <-chErr
-}
-
-func pullTagAndRemove(ctx context.Context, client client.APIClient, ref string, tag string) error {
- resp, err := client.ImagePull(ctx, ref, types.ImagePullOptions{})
- if err != nil {
- return errors.Wrapf(err, "failed to pull %s", ref)
- }
- defer resp.Close()
- fd, isTerminal := term.GetFdInfo(os.Stdout)
- if err := jsonmessage.DisplayJSONMessagesStream(resp, os.Stdout, fd, isTerminal, nil); err != nil {
- return err
- }
-
- if err := client.ImageTag(ctx, ref, tag); err != nil {
- return errors.Wrapf(err, "failed to tag %s as %s", ref, tag)
- }
- _, err = client.ImageRemove(ctx, ref, types.ImageRemoveOptions{})
- return errors.Wrapf(err, "failed to remove %s", ref)
-
-}
-
-func readFrozenImageList(dockerfilePath string, images []string) (map[string]string, error) {
- f, err := os.Open(dockerfilePath)
- if err != nil {
- return nil, errors.Wrap(err, "error reading dockerfile")
- }
- defer f.Close()
- ls := make(map[string]string)
-
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := strings.Fields(scanner.Text())
- if len(line) < 3 {
- continue
- }
- if !(line[0] == "RUN" && line[1] == "./contrib/download-frozen-image-v2.sh") {
- continue
- }
-
- for scanner.Scan() {
- img := strings.TrimSpace(scanner.Text())
- img = strings.TrimSuffix(img, "\\")
- img = strings.TrimSpace(img)
- split := strings.Split(img, "@")
- if len(split) < 2 {
- break
- }
-
- for _, i := range images {
- if split[0] == i {
- ls[i] = img
- break
- }
- }
- }
- }
- return ls, nil
-}
diff --git a/internal/test/fixtures/plugin/basic/basic.go b/internal/test/fixtures/plugin/basic/basic.go
deleted file mode 100644
index 892272826f..0000000000
--- a/internal/test/fixtures/plugin/basic/basic.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package main
-
-import (
- "fmt"
- "net"
- "net/http"
- "os"
- "path/filepath"
-)
-
-func main() {
- p, err := filepath.Abs(filepath.Join("run", "docker", "plugins"))
- if err != nil {
- panic(err)
- }
- if err := os.MkdirAll(p, 0755); err != nil {
- panic(err)
- }
- l, err := net.Listen("unix", filepath.Join(p, "basic.sock"))
- if err != nil {
- panic(err)
- }
-
- mux := http.NewServeMux()
- server := http.Server{
- Addr: l.Addr().String(),
- Handler: http.NewServeMux(),
- }
- mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1.1+json")
- fmt.Println(w, `{"Implements": ["dummy"]}`)
- })
- server.Serve(l)
-}
diff --git a/internal/test/fixtures/plugin/plugin.go b/internal/test/fixtures/plugin/plugin.go
deleted file mode 100644
index 93f5f99fed..0000000000
--- a/internal/test/fixtures/plugin/plugin.go
+++ /dev/null
@@ -1,216 +0,0 @@
-package plugin // import "github.com/docker/docker/internal/test/fixtures/plugin"
-
-import (
- "context"
- "encoding/json"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "time"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/pkg/archive"
- "github.com/docker/docker/plugin"
- "github.com/docker/docker/registry"
- "github.com/pkg/errors"
-)
-
-// CreateOpt is passed used to change the default plugin config before
-// creating it
-type CreateOpt func(*Config)
-
-// Config wraps types.PluginConfig to provide some extra state for options
-// extra customizations on the plugin details, such as using a custom binary to
-// create the plugin with.
-type Config struct {
- *types.PluginConfig
- binPath string
-}
-
-// WithBinary is a CreateOpt to set an custom binary to create the plugin with.
-// This binary must be statically compiled.
-func WithBinary(bin string) CreateOpt {
- return func(cfg *Config) {
- cfg.binPath = bin
- }
-}
-
-// CreateClient is the interface used for `BuildPlugin` to interact with the
-// daemon.
-type CreateClient interface {
- PluginCreate(context.Context, io.Reader, types.PluginCreateOptions) error
-}
-
-// Create creates a new plugin with the specified name
-func Create(ctx context.Context, c CreateClient, name string, opts ...CreateOpt) error {
- tmpDir, err := ioutil.TempDir("", "create-test-plugin")
- if err != nil {
- return err
- }
- defer os.RemoveAll(tmpDir)
-
- tar, err := makePluginBundle(tmpDir, opts...)
- if err != nil {
- return err
- }
- defer tar.Close()
-
- ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
- defer cancel()
-
- return c.PluginCreate(ctx, tar, types.PluginCreateOptions{RepoName: name})
-}
-
-// CreateInRegistry makes a plugin (locally) and pushes it to a registry.
-// This does not use a dockerd instance to create or push the plugin.
-// If you just want to create a plugin in some daemon, use `Create`.
-//
-// This can be useful when testing plugins on swarm where you don't really want
-// the plugin to exist on any of the daemons (immediately) and there needs to be
-// some way to distribute the plugin.
-func CreateInRegistry(ctx context.Context, repo string, auth *types.AuthConfig, opts ...CreateOpt) error {
- tmpDir, err := ioutil.TempDir("", "create-test-plugin-local")
- if err != nil {
- return err
- }
- defer os.RemoveAll(tmpDir)
-
- inPath := filepath.Join(tmpDir, "plugin")
- if err := os.MkdirAll(inPath, 0755); err != nil {
- return errors.Wrap(err, "error creating plugin root")
- }
-
- tar, err := makePluginBundle(inPath, opts...)
- if err != nil {
- return err
- }
- defer tar.Close()
-
- dummyExec := func(m *plugin.Manager) (plugin.Executor, error) {
- return nil, nil
- }
-
- regService, err := registry.NewService(registry.ServiceOptions{})
- if err != nil {
- return err
- }
-
- managerConfig := plugin.ManagerConfig{
- Store: plugin.NewStore(),
- RegistryService: regService,
- Root: filepath.Join(tmpDir, "root"),
- ExecRoot: "/run/docker", // manager init fails if not set
- CreateExecutor: dummyExec,
- LogPluginEvent: func(id, name, action string) {}, // panics when not set
- }
- manager, err := plugin.NewManager(managerConfig)
- if err != nil {
- return errors.Wrap(err, "error creating plugin manager")
- }
-
- ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
- defer cancel()
- if err := manager.CreateFromContext(ctx, tar, &types.PluginCreateOptions{RepoName: repo}); err != nil {
- return err
- }
-
- if auth == nil {
- auth = &types.AuthConfig{}
- }
- err = manager.Push(ctx, repo, nil, auth, ioutil.Discard)
- return errors.Wrap(err, "error pushing plugin")
-}
-
-func makePluginBundle(inPath string, opts ...CreateOpt) (io.ReadCloser, error) {
- p := &types.PluginConfig{
- Interface: types.PluginConfigInterface{
- Socket: "basic.sock",
- Types: []types.PluginInterfaceType{{Capability: "docker.dummy/1.0"}},
- },
- Entrypoint: []string{"/basic"},
- }
- cfg := &Config{
- PluginConfig: p,
- }
- for _, o := range opts {
- o(cfg)
- }
- if cfg.binPath == "" {
- binPath, err := ensureBasicPluginBin()
- if err != nil {
- return nil, err
- }
- cfg.binPath = binPath
- }
-
- configJSON, err := json.Marshal(p)
- if err != nil {
- return nil, err
- }
- if err := ioutil.WriteFile(filepath.Join(inPath, "config.json"), configJSON, 0644); err != nil {
- return nil, err
- }
- if err := os.MkdirAll(filepath.Join(inPath, "rootfs", filepath.Dir(p.Entrypoint[0])), 0755); err != nil {
- return nil, errors.Wrap(err, "error creating plugin rootfs dir")
- }
-
- // Ensure the mount target paths exist
- for _, m := range p.Mounts {
- var stat os.FileInfo
- if m.Source != nil {
- stat, err = os.Stat(*m.Source)
- if err != nil && !os.IsNotExist(err) {
- return nil, err
- }
- }
-
- if stat == nil || stat.IsDir() {
- var mode os.FileMode = 0755
- if stat != nil {
- mode = stat.Mode()
- }
- if err := os.MkdirAll(filepath.Join(inPath, "rootfs", m.Destination), mode); err != nil {
- return nil, errors.Wrap(err, "error preparing plugin mount destination path")
- }
- } else {
- if err := os.MkdirAll(filepath.Join(inPath, "rootfs", filepath.Dir(m.Destination)), 0755); err != nil {
- return nil, errors.Wrap(err, "error preparing plugin mount destination dir")
- }
- f, err := os.Create(filepath.Join(inPath, "rootfs", m.Destination))
- if err != nil && !os.IsExist(err) {
- return nil, errors.Wrap(err, "error preparing plugin mount destination file")
- }
- if f != nil {
- f.Close()
- }
- }
- }
- if err := archive.NewDefaultArchiver().CopyFileWithTar(cfg.binPath, filepath.Join(inPath, "rootfs", p.Entrypoint[0])); err != nil {
- return nil, errors.Wrap(err, "error copying plugin binary to rootfs path")
- }
- tar, err := archive.Tar(inPath, archive.Uncompressed)
- return tar, errors.Wrap(err, "error making plugin archive")
-}
-
-func ensureBasicPluginBin() (string, error) {
- name := "docker-basic-plugin"
- p, err := exec.LookPath(name)
- if err == nil {
- return p, nil
- }
-
- goBin, err := exec.LookPath("go")
- if err != nil {
- return "", err
- }
- installPath := filepath.Join(os.Getenv("GOPATH"), "bin", name)
- sourcePath := filepath.Join("github.com", "docker", "docker", "internal", "test", "fixtures", "plugin", "basic")
- cmd := exec.Command(goBin, "build", "-o", installPath, sourcePath)
- cmd.Env = append(os.Environ(), "CGO_ENABLED=0")
- if out, err := cmd.CombinedOutput(); err != nil {
- return "", errors.Wrapf(err, "error building basic plugin bin: %s", string(out))
- }
- return installPath, nil
-}
diff --git a/internal/test/helper.go b/internal/test/helper.go
deleted file mode 100644
index 1b9fd75090..0000000000
--- a/internal/test/helper.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package test
-
-// HelperT is a subset of testing.T that implements the Helper function
-type HelperT interface {
- Helper()
-}
diff --git a/internal/test/registry/ops.go b/internal/test/registry/ops.go
deleted file mode 100644
index c004f37424..0000000000
--- a/internal/test/registry/ops.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package registry
-
-// Schema1 sets the registry to serve v1 api
-func Schema1(c *Config) {
- c.schema1 = true
-}
-
-// Htpasswd sets the auth method with htpasswd
-func Htpasswd(c *Config) {
- c.auth = "htpasswd"
-}
-
-// Token sets the auth method to token, with the specified token url
-func Token(tokenURL string) func(*Config) {
- return func(c *Config) {
- c.auth = "token"
- c.tokenURL = tokenURL
- }
-}
-
-// URL sets the registry url
-func URL(registryURL string) func(*Config) {
- return func(c *Config) {
- c.registryURL = registryURL
- }
-}
diff --git a/internal/test/registry/registry.go b/internal/test/registry/registry.go
deleted file mode 100644
index b6128d3ba4..0000000000
--- a/internal/test/registry/registry.go
+++ /dev/null
@@ -1,255 +0,0 @@
-package registry // import "github.com/docker/docker/internal/test/registry"
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "os/exec"
- "path/filepath"
- "time"
-
- "github.com/docker/docker/internal/test"
- "github.com/opencontainers/go-digest"
- "gotest.tools/assert"
-)
-
-const (
- // V2binary is the name of the registry v2 binary
- V2binary = "registry-v2"
- // V2binarySchema1 is the name of the registry that serve schema1
- V2binarySchema1 = "registry-v2-schema1"
- // DefaultURL is the default url that will be used by the registry (if not specified otherwise)
- DefaultURL = "127.0.0.1:5000"
-)
-
-type testingT interface {
- assert.TestingT
- logT
- Fatal(...interface{})
- Fatalf(string, ...interface{})
-}
-
-type logT interface {
- Logf(string, ...interface{})
-}
-
-// V2 represent a registry version 2
-type V2 struct {
- cmd *exec.Cmd
- registryURL string
- dir string
- auth string
- username string
- password string
- email string
-}
-
-// Config contains the test registry configuration
-type Config struct {
- schema1 bool
- auth string
- tokenURL string
- registryURL string
-}
-
-// NewV2 creates a v2 registry server
-func NewV2(t testingT, ops ...func(*Config)) *V2 {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- c := &Config{
- registryURL: DefaultURL,
- }
- for _, op := range ops {
- op(c)
- }
- tmp, err := ioutil.TempDir("", "registry-test-")
- assert.NilError(t, err)
- template := `version: 0.1
-loglevel: debug
-storage:
- filesystem:
- rootdirectory: %s
-http:
- addr: %s
-%s`
- var (
- authTemplate string
- username string
- password string
- email string
- )
- switch c.auth {
- case "htpasswd":
- htpasswdPath := filepath.Join(tmp, "htpasswd")
- // generated with: htpasswd -Bbn testuser testpassword
- userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m"
- username = "testuser"
- password = "testpassword"
- email = "test@test.org"
- err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644))
- assert.NilError(t, err)
- authTemplate = fmt.Sprintf(`auth:
- htpasswd:
- realm: basic-realm
- path: %s
-`, htpasswdPath)
- case "token":
- authTemplate = fmt.Sprintf(`auth:
- token:
- realm: %s
- service: "registry"
- issuer: "auth-registry"
- rootcertbundle: "fixtures/registry/cert.pem"
-`, c.tokenURL)
- }
-
- confPath := filepath.Join(tmp, "config.yaml")
- config, err := os.Create(confPath)
- assert.NilError(t, err)
- defer config.Close()
-
- if _, err := fmt.Fprintf(config, template, tmp, c.registryURL, authTemplate); err != nil {
- // FIXME(vdemeester) use a defer/clean func
- os.RemoveAll(tmp)
- t.Fatal(err)
- }
-
- binary := V2binary
- if c.schema1 {
- binary = V2binarySchema1
- }
- cmd := exec.Command(binary, confPath)
- if err := cmd.Start(); err != nil {
- // FIXME(vdemeester) use a defer/clean func
- os.RemoveAll(tmp)
- t.Fatal(err)
- }
- return &V2{
- cmd: cmd,
- dir: tmp,
- auth: c.auth,
- username: username,
- password: password,
- email: email,
- registryURL: c.registryURL,
- }
-}
-
-// WaitReady waits for the registry to be ready to serve requests (or fail after a while)
-func (r *V2) WaitReady(t testingT) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- var err error
- for i := 0; i != 50; i++ {
- if err = r.Ping(); err == nil {
- return
- }
- time.Sleep(100 * time.Millisecond)
- }
- t.Fatalf("timeout waiting for test registry to become available: %v", err)
-}
-
-// Ping sends an http request to the current registry, and fail if it doesn't respond correctly
-func (r *V2) Ping() error {
- // We always ping through HTTP for our test registry.
- resp, err := http.Get(fmt.Sprintf("http://%s/v2/", r.registryURL))
- if err != nil {
- return err
- }
- resp.Body.Close()
-
- fail := resp.StatusCode != http.StatusOK
- if r.auth != "" {
- // unauthorized is a _good_ status when pinging v2/ and it needs auth
- fail = fail && resp.StatusCode != http.StatusUnauthorized
- }
- if fail {
- return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
- }
- return nil
-}
-
-// Close kills the registry server
-func (r *V2) Close() {
- r.cmd.Process.Kill()
- r.cmd.Process.Wait()
- os.RemoveAll(r.dir)
-}
-
-func (r *V2) getBlobFilename(blobDigest digest.Digest) string {
- // Split the digest into its algorithm and hex components.
- dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex()
-
- // The path to the target blob data looks something like:
- // baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data"
- return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", r.dir, dgstAlg, dgstHex[:2], dgstHex)
-}
-
-// ReadBlobContents read the file corresponding to the specified digest
-func (r *V2) ReadBlobContents(t assert.TestingT, blobDigest digest.Digest) []byte {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- // Load the target manifest blob.
- manifestBlob, err := ioutil.ReadFile(r.getBlobFilename(blobDigest))
- assert.NilError(t, err, "unable to read blob")
- return manifestBlob
-}
-
-// WriteBlobContents write the file corresponding to the specified digest with the given content
-func (r *V2) WriteBlobContents(t assert.TestingT, blobDigest digest.Digest, data []byte) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- err := ioutil.WriteFile(r.getBlobFilename(blobDigest), data, os.FileMode(0644))
- assert.NilError(t, err, "unable to write malicious data blob")
-}
-
-// TempMoveBlobData moves the existing data file aside, so that we can replace it with a
-// malicious blob of data for example.
-func (r *V2) TempMoveBlobData(t testingT, blobDigest digest.Digest) (undo func()) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- tempFile, err := ioutil.TempFile("", "registry-temp-blob-")
- assert.NilError(t, err, "unable to get temporary blob file")
- tempFile.Close()
-
- blobFilename := r.getBlobFilename(blobDigest)
-
- // Move the existing data file aside, so that we can replace it with a
- // another blob of data.
- if err := os.Rename(blobFilename, tempFile.Name()); err != nil {
- // FIXME(vdemeester) use a defer/clean func
- os.Remove(tempFile.Name())
- t.Fatalf("unable to move data blob: %s", err)
- }
-
- return func() {
- os.Rename(tempFile.Name(), blobFilename)
- os.Remove(tempFile.Name())
- }
-}
-
-// Username returns the configured user name of the server
-func (r *V2) Username() string {
- return r.username
-}
-
-// Password returns the configured password of the server
-func (r *V2) Password() string {
- return r.password
-}
-
-// Email returns the configured email of the server
-func (r *V2) Email() string {
- return r.email
-}
-
-// Path returns the path where the registry write data
-func (r *V2) Path() string {
- return filepath.Join(r.dir, "docker", "registry", "v2")
-}
diff --git a/internal/test/registry/registry_mock.go b/internal/test/registry/registry_mock.go
deleted file mode 100644
index d139401a62..0000000000
--- a/internal/test/registry/registry_mock.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package registry // import "github.com/docker/docker/internal/test/registry"
-
-import (
- "net/http"
- "net/http/httptest"
- "regexp"
- "strings"
- "sync"
-
- "github.com/docker/docker/internal/test"
-)
-
-type handlerFunc func(w http.ResponseWriter, r *http.Request)
-
-// Mock represent a registry mock
-type Mock struct {
- server *httptest.Server
- hostport string
- handlers map[string]handlerFunc
- mu sync.Mutex
-}
-
-// RegisterHandler register the specified handler for the registry mock
-func (tr *Mock) RegisterHandler(path string, h handlerFunc) {
- tr.mu.Lock()
- defer tr.mu.Unlock()
- tr.handlers[path] = h
-}
-
-// NewMock creates a registry mock
-func NewMock(t testingT) (*Mock, error) {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- testReg := &Mock{handlers: make(map[string]handlerFunc)}
-
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- url := r.URL.String()
-
- var matched bool
- var err error
- for re, function := range testReg.handlers {
- matched, err = regexp.MatchString(re, url)
- if err != nil {
- t.Fatal("Error with handler regexp")
- }
- if matched {
- function(w, r)
- break
- }
- }
-
- if !matched {
- t.Fatalf("Unable to match %s with regexp", url)
- }
- }))
-
- testReg.server = ts
- testReg.hostport = strings.Replace(ts.URL, "http://", "", 1)
- return testReg, nil
-}
-
-// URL returns the url of the registry
-func (tr *Mock) URL() string {
- return tr.hostport
-}
-
-// Close closes mock and releases resources
-func (tr *Mock) Close() {
- tr.server.Close()
-}
diff --git a/internal/test/request/npipe.go b/internal/test/request/npipe.go
deleted file mode 100644
index e6ab03945e..0000000000
--- a/internal/test/request/npipe.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// +build !windows
-
-package request
-
-import (
- "net"
- "time"
-)
-
-func npipeDial(path string, timeout time.Duration) (net.Conn, error) {
- panic("npipe protocol only supported on Windows")
-}
diff --git a/internal/test/request/npipe_windows.go b/internal/test/request/npipe_windows.go
deleted file mode 100644
index a268aac922..0000000000
--- a/internal/test/request/npipe_windows.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package request
-
-import (
- "net"
- "time"
-
- "github.com/Microsoft/go-winio"
-)
-
-func npipeDial(path string, timeout time.Duration) (net.Conn, error) {
- return winio.DialPipe(path, &timeout)
-}
diff --git a/internal/test/request/ops.go b/internal/test/request/ops.go
deleted file mode 100644
index c85308c476..0000000000
--- a/internal/test/request/ops.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package request
-
-import (
- "bytes"
- "encoding/json"
- "io"
- "io/ioutil"
- "net/http"
- "strings"
-)
-
-// Options defines request options, like request modifiers and which host to target
-type Options struct {
- host string
- requestModifiers []func(*http.Request) error
-}
-
-// Host creates a modifier that sets the specified host as the request URL host
-func Host(host string) func(*Options) {
- return func(o *Options) {
- o.host = host
- }
-}
-
-// With adds a request modifier to the options
-func With(f func(*http.Request) error) func(*Options) {
- return func(o *Options) {
- o.requestModifiers = append(o.requestModifiers, f)
- }
-}
-
-// Method creates a modifier that sets the specified string as the request method
-func Method(method string) func(*Options) {
- return With(func(req *http.Request) error {
- req.Method = method
- return nil
- })
-}
-
-// RawString sets the specified string as body for the request
-func RawString(content string) func(*Options) {
- return RawContent(ioutil.NopCloser(strings.NewReader(content)))
-}
-
-// RawContent sets the specified reader as body for the request
-func RawContent(reader io.ReadCloser) func(*Options) {
- return With(func(req *http.Request) error {
- req.Body = reader
- return nil
- })
-}
-
-// ContentType sets the specified Content-Type request header
-func ContentType(contentType string) func(*Options) {
- return With(func(req *http.Request) error {
- req.Header.Set("Content-Type", contentType)
- return nil
- })
-}
-
-// JSON sets the Content-Type request header to json
-func JSON(o *Options) {
- ContentType("application/json")(o)
-}
-
-// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets
-// the Content-Type header of the request.
-func JSONBody(data interface{}) func(*Options) {
- return With(func(req *http.Request) error {
- jsonData := bytes.NewBuffer(nil)
- if err := json.NewEncoder(jsonData).Encode(data); err != nil {
- return err
- }
- req.Body = ioutil.NopCloser(jsonData)
- req.Header.Set("Content-Type", "application/json")
- return nil
- })
-}
diff --git a/internal/test/request/request.go b/internal/test/request/request.go
deleted file mode 100644
index 6bf70c7437..0000000000
--- a/internal/test/request/request.go
+++ /dev/null
@@ -1,223 +0,0 @@
-package request // import "github.com/docker/docker/internal/test/request"
-
-import (
- "context"
- "crypto/tls"
- "fmt"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "os"
- "path/filepath"
- "time"
-
- "github.com/docker/docker/client"
- "github.com/docker/docker/internal/test"
- "github.com/docker/docker/internal/test/environment"
- "github.com/docker/docker/opts"
- "github.com/docker/docker/pkg/ioutils"
- "github.com/docker/go-connections/sockets"
- "github.com/docker/go-connections/tlsconfig"
- "github.com/pkg/errors"
- "gotest.tools/assert"
-)
-
-// NewAPIClient returns a docker API client configured from environment variables
-func NewAPIClient(t assert.TestingT, ops ...client.Opt) client.APIClient {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- ops = append([]client.Opt{client.FromEnv}, ops...)
- clt, err := client.NewClientWithOpts(ops...)
- assert.NilError(t, err)
- return clt
-}
-
-// DaemonTime provides the current time on the daemon host
-func DaemonTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) time.Time {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- if testEnv.IsLocalDaemon() {
- return time.Now()
- }
-
- info, err := client.Info(ctx)
- assert.NilError(t, err)
-
- dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
- assert.NilError(t, err, "invalid time format in GET /info response")
- return dt
-}
-
-// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision.
-// It return the time formatted how the client sends timestamps to the server.
-func DaemonUnixTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) string {
- if ht, ok := t.(test.HelperT); ok {
- ht.Helper()
- }
- dt := DaemonTime(ctx, t, client, testEnv)
- return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
-}
-
-// Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers
-func Post(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
- return Do(endpoint, append(modifiers, Method(http.MethodPost))...)
-}
-
-// Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers
-func Delete(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
- return Do(endpoint, append(modifiers, Method(http.MethodDelete))...)
-}
-
-// Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers
-func Get(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
- return Do(endpoint, modifiers...)
-}
-
-// Head creates and execute a HEAD request on the specified host and endpoint, with the specified request modifiers
-func Head(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
- return Do(endpoint, append(modifiers, Method(http.MethodHead))...)
-}
-
-// Do creates and execute a request on the specified endpoint, with the specified request modifiers
-func Do(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
- opts := &Options{
- host: DaemonHost(),
- }
- for _, mod := range modifiers {
- mod(opts)
- }
- req, err := newRequest(endpoint, opts)
- if err != nil {
- return nil, nil, err
- }
- client, err := newHTTPClient(opts.host)
- if err != nil {
- return nil, nil, err
- }
- resp, err := client.Do(req)
- var body io.ReadCloser
- if resp != nil {
- body = ioutils.NewReadCloserWrapper(resp.Body, func() error {
- defer resp.Body.Close()
- return nil
- })
- }
- return resp, body, err
-}
-
-// ReadBody read the specified ReadCloser content and returns it
-func ReadBody(b io.ReadCloser) ([]byte, error) {
- defer b.Close()
- return ioutil.ReadAll(b)
-}
-
-// newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers
-func newRequest(endpoint string, opts *Options) (*http.Request, error) {
- hostURL, err := client.ParseHostURL(opts.host)
- if err != nil {
- return nil, errors.Wrapf(err, "failed parsing url %q", opts.host)
- }
- req, err := http.NewRequest("GET", endpoint, nil)
- if err != nil {
- return nil, errors.Wrap(err, "failed to create request")
- }
-
- if os.Getenv("DOCKER_TLS_VERIFY") != "" {
- req.URL.Scheme = "https"
- } else {
- req.URL.Scheme = "http"
- }
- req.URL.Host = hostURL.Host
-
- for _, config := range opts.requestModifiers {
- if err := config(req); err != nil {
- return nil, err
- }
- }
-
- return req, nil
-}
-
-// newHTTPClient creates an http client for the specific host
-// TODO: Share more code with client.defaultHTTPClient
-func newHTTPClient(host string) (*http.Client, error) {
- // FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
- hostURL, err := client.ParseHostURL(host)
- if err != nil {
- return nil, err
- }
- transport := new(http.Transport)
- if hostURL.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
- // Setup the socket TLS configuration.
- tlsConfig, err := getTLSConfig()
- if err != nil {
- return nil, err
- }
- transport = &http.Transport{TLSClientConfig: tlsConfig}
- }
- transport.DisableKeepAlives = true
- err = sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
- return &http.Client{Transport: transport}, err
-}
-
-func getTLSConfig() (*tls.Config, error) {
- dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
-
- if dockerCertPath == "" {
- return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable")
- }
-
- option := &tlsconfig.Options{
- CAFile: filepath.Join(dockerCertPath, "ca.pem"),
- CertFile: filepath.Join(dockerCertPath, "cert.pem"),
- KeyFile: filepath.Join(dockerCertPath, "key.pem"),
- }
- tlsConfig, err := tlsconfig.Client(*option)
- if err != nil {
- return nil, err
- }
-
- return tlsConfig, nil
-}
-
-// DaemonHost return the daemon host string for this test execution
-func DaemonHost() string {
- daemonURLStr := "unix://" + opts.DefaultUnixSocket
- if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
- daemonURLStr = daemonHostVar
- }
- return daemonURLStr
-}
-
-// SockConn opens a connection on the specified socket
-func SockConn(timeout time.Duration, daemon string) (net.Conn, error) {
- daemonURL, err := url.Parse(daemon)
- if err != nil {
- return nil, errors.Wrapf(err, "could not parse url %q", daemon)
- }
-
- var c net.Conn
- switch daemonURL.Scheme {
- case "npipe":
- return npipeDial(daemonURL.Path, timeout)
- case "unix":
- return net.DialTimeout(daemonURL.Scheme, daemonURL.Path, timeout)
- case "tcp":
- if os.Getenv("DOCKER_TLS_VERIFY") != "" {
- // Setup the socket TLS configuration.
- tlsConfig, err := getTLSConfig()
- if err != nil {
- return nil, err
- }
- dialer := &net.Dialer{Timeout: timeout}
- return tls.DialWithDialer(dialer, daemonURL.Scheme, daemonURL.Host, tlsConfig)
- }
- return net.DialTimeout(daemonURL.Scheme, daemonURL.Host, timeout)
- default:
- return c, errors.Errorf("unknown scheme %v (%s)", daemonURL.Scheme, daemon)
- }
-}
diff --git a/internal/testutil/helpers.go b/internal/testutil/helpers.go
deleted file mode 100644
index 38cd1693f5..0000000000
--- a/internal/testutil/helpers.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package testutil // import "github.com/docker/docker/internal/testutil"
-
-import (
- "io"
-)
-
-// DevZero acts like /dev/zero but in an OS-independent fashion.
-var DevZero io.Reader = devZero{}
-
-type devZero struct{}
-
-func (d devZero) Read(p []byte) (n int, err error) {
- for i := range p {
- p[i] = 0
- }
- return len(p), nil
-}
diff --git a/internal/testutil/stringutils.go b/internal/testutil/stringutils.go
deleted file mode 100644
index 574aeb51f2..0000000000
--- a/internal/testutil/stringutils.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package testutil // import "github.com/docker/docker/internal/testutil"
-
-import "math/rand"
-
-// GenerateRandomAlphaOnlyString generates an alphabetical random string with length n.
-func GenerateRandomAlphaOnlyString(n int) string {
- // make a really long string
- letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
- b := make([]byte, n)
- for i := range b {
- b[i] = letters[rand.Intn(len(letters))]
- }
- return string(b)
-}
diff --git a/internal/testutil/stringutils_test.go b/internal/testutil/stringutils_test.go
deleted file mode 100644
index 753aac966d..0000000000
--- a/internal/testutil/stringutils_test.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package testutil // import "github.com/docker/docker/internal/testutil"
-
-import (
- "testing"
-
- "gotest.tools/assert"
- is "gotest.tools/assert/cmp"
-)
-
-func testLengthHelper(generator func(int) string, t *testing.T) {
- expectedLength := 20
- s := generator(expectedLength)
- assert.Check(t, is.Equal(expectedLength, len(s)))
-}
-
-func testUniquenessHelper(generator func(int) string, t *testing.T) {
- repeats := 25
- set := make(map[string]struct{}, repeats)
- for i := 0; i < repeats; i = i + 1 {
- str := generator(64)
- assert.Check(t, is.Equal(64, len(str)))
- _, ok := set[str]
- assert.Check(t, !ok, "Random number is repeated")
- set[str] = struct{}{}
- }
-}
-
-func TestGenerateRandomAlphaOnlyStringLength(t *testing.T) {
- testLengthHelper(GenerateRandomAlphaOnlyString, t)
-}
-
-func TestGenerateRandomAlphaOnlyStringUniqueness(t *testing.T) {
- testUniquenessHelper(GenerateRandomAlphaOnlyString, t)
-}