Merge component 'engine' from git@github.com:moby/moby master
This commit is contained in:
@@ -26,7 +26,7 @@ import (
|
||||
// We'll also end up with many tasks all pointing to the same plugin ID.
|
||||
//
|
||||
// TODO(@cpuguy83): registry auth is intentionally not supported until we work out
|
||||
// the right way to pass registry crednetials via secrets.
|
||||
// the right way to pass registry credentials via secrets.
|
||||
type Controller struct {
|
||||
backend Backend
|
||||
spec runtime.PluginSpec
|
||||
|
||||
@@ -409,7 +409,7 @@ func (d *Driver) terminateServiceVM(id, context string, force bool) (err error)
|
||||
svm.signalStopFinished(err)
|
||||
}()
|
||||
|
||||
// Now it's possible that the serivce VM failed to start and now we are trying to termiante it.
|
||||
// Now it's possible that the serivce VM failed to start and now we are trying to terminate it.
|
||||
// In this case, we will relay the error to the goroutines waiting for this vm to stop.
|
||||
if err := svm.getStartError(); err != nil {
|
||||
logrus.Debugf("lcowdriver: terminateservicevm: %s had failed to start up: %s", id, err)
|
||||
|
||||
@@ -42,7 +42,7 @@ func PutMessage(msg *Message) {
|
||||
messagePool.Put(msg)
|
||||
}
|
||||
|
||||
// Message is datastructure that represents piece of output produced by some
|
||||
// Message is data structure that represents piece of output produced by some
|
||||
// container. The Line member is a slice of an array whose contents can be
|
||||
// changed after a log driver's Log() method returns.
|
||||
//
|
||||
@@ -133,7 +133,7 @@ func (w *LogWatcher) WatchClose() <-chan struct{} {
|
||||
return w.closeNotifier
|
||||
}
|
||||
|
||||
// Capability defines the list of capabilties that a driver can implement
|
||||
// Capability defines the list of capabilities that a driver can implement
|
||||
// These capabilities are not required to be a logging driver, however do
|
||||
// determine how a logging driver can be used
|
||||
type Capability struct {
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestSessionCreate(c *check.C) {
|
||||
testRequires(c, ExperimentalDaemon)
|
||||
|
||||
res, body, err := request.Post("/session", func(r *http.Request) error {
|
||||
r.Header.Set("X-Docker-Expose-Session-Uuid", "testsessioncreate") // so we don't block default name if something else is using it
|
||||
r.Header.Set("Upgrade", "h2c")
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusSwitchingProtocols)
|
||||
c.Assert(res.Header.Get("Upgrade"), checker.Equals, "h2c")
|
||||
c.Assert(body.Close(), checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestSessionCreateWithBadUpgrade(c *check.C) {
|
||||
testRequires(c, ExperimentalDaemon)
|
||||
|
||||
res, body, err := request.Post("/session")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
c.Assert(out, checker.Contains, "no upgrade")
|
||||
|
||||
res, body, err = request.Post("/session", func(r *http.Request) error {
|
||||
r.Header.Set("Upgrade", "foo")
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
buf, err = request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out = string(buf)
|
||||
c.Assert(out, checker.Contains, "not supported")
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestPause(c *check.C) {
|
||||
testRequires(c, IsPausable)
|
||||
|
||||
name := "testeventpause"
|
||||
runSleepingContainer(c, "-d", "--name", name)
|
||||
|
||||
cli.DockerCmd(c, "pause", name)
|
||||
pausedContainers := strings.Fields(
|
||||
cli.DockerCmd(c, "ps", "-f", "status=paused", "-q", "-a").Combined(),
|
||||
)
|
||||
c.Assert(len(pausedContainers), checker.Equals, 1)
|
||||
|
||||
cli.DockerCmd(c, "unpause", name)
|
||||
|
||||
out := cli.DockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c)).Combined()
|
||||
events := strings.Split(strings.TrimSpace(out), "\n")
|
||||
actions := eventActionsByIDAndType(c, events, name, "container")
|
||||
|
||||
c.Assert(actions[len(actions)-2], checker.Equals, "pause")
|
||||
c.Assert(actions[len(actions)-1], checker.Equals, "unpause")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
|
||||
testRequires(c, IsPausable)
|
||||
|
||||
containers := []string{
|
||||
"testpausewithmorecontainers1",
|
||||
"testpausewithmorecontainers2",
|
||||
}
|
||||
for _, name := range containers {
|
||||
runSleepingContainer(c, "-d", "--name", name)
|
||||
}
|
||||
cli.DockerCmd(c, append([]string{"pause"}, containers...)...)
|
||||
pausedContainers := strings.Fields(
|
||||
cli.DockerCmd(c, "ps", "-f", "status=paused", "-q", "-a").Combined(),
|
||||
)
|
||||
c.Assert(len(pausedContainers), checker.Equals, len(containers))
|
||||
|
||||
cli.DockerCmd(c, append([]string{"unpause"}, containers...)...)
|
||||
|
||||
out := cli.DockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c)).Combined()
|
||||
events := strings.Split(strings.TrimSpace(out), "\n")
|
||||
|
||||
for _, name := range containers {
|
||||
actions := eventActionsByIDAndType(c, events, name, "container")
|
||||
|
||||
c.Assert(actions[len(actions)-2], checker.Equals, "pause")
|
||||
c.Assert(actions[len(actions)-1], checker.Equals, "unpause")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPauseFailsOnWindowsServerContainers(c *check.C) {
|
||||
testRequires(c, DaemonIsWindows, NotPausable)
|
||||
runSleepingContainer(c, "-d", "--name=test")
|
||||
out, _, _ := dockerCmdWithError("pause", "test")
|
||||
c.Assert(out, checker.Contains, "cannot pause Windows Server Containers")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestStopPausedContainer(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
|
||||
id := runSleepingContainer(c)
|
||||
cli.WaitRun(c, id)
|
||||
cli.DockerCmd(c, "pause", id)
|
||||
cli.DockerCmd(c, "stop", id)
|
||||
cli.WaitForInspectResult(c, id, "{{.State.Running}}", "false", 30*time.Second)
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// This is a regression test for #36145
|
||||
// It ensures that a container can be started when the daemon was improperly
|
||||
// shutdown when the daemon is brought back up.
|
||||
//
|
||||
// The regression is due to improper error handling preventing a container from
|
||||
// being restored and as such have the resources cleaned up.
|
||||
//
|
||||
// To test this, we need to kill dockerd, then kill both the containerd-shim and
|
||||
// the container process, then start dockerd back up and attempt to start the
|
||||
// container again.
|
||||
func TestContainerStartOnDaemonRestart(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
d := daemon.New(t, "", "dockerd", daemon.Config{})
|
||||
d.StartWithBusybox(t, "--iptables=false")
|
||||
defer d.Stop(t)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NoError(t, err, "error creating client")
|
||||
|
||||
ctx := context.Background()
|
||||
c, err := client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"top"},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
assert.NoError(t, err, "error creating test container")
|
||||
defer client.ContainerRemove(ctx, c.ID, types.ContainerRemoveOptions{Force: true})
|
||||
|
||||
err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
|
||||
assert.NoError(t, err, "error starting test container")
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, c.ID)
|
||||
assert.NoError(t, err, "error getting inspect data")
|
||||
|
||||
ppid := getContainerdShimPid(t, inspect)
|
||||
|
||||
err = d.Kill()
|
||||
assert.NoError(t, err, "failed to kill test daemon")
|
||||
|
||||
err = unix.Kill(inspect.State.Pid, unix.SIGKILL)
|
||||
assert.NoError(t, err, "failed to kill container process")
|
||||
|
||||
err = unix.Kill(ppid, unix.SIGKILL)
|
||||
assert.NoError(t, err, "failed to kill containerd-shim")
|
||||
|
||||
d.Start(t, "--iptables=false")
|
||||
|
||||
err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
|
||||
assert.NoError(t, err, "failed to start test container")
|
||||
}
|
||||
|
||||
func getContainerdShimPid(t *testing.T, c types.ContainerJSON) int {
|
||||
statB, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", c.State.Pid))
|
||||
assert.NoError(t, err, "error looking up containerd-shim pid")
|
||||
|
||||
// ppid is the 4th entry in `/proc/pid/stat`
|
||||
ppid, err := strconv.Atoi(strings.Fields(string(statB))[3])
|
||||
assert.NoError(t, err, "error converting ppid field to int")
|
||||
|
||||
assert.NotEqual(t, ppid, 1, "got unexpected ppid")
|
||||
return ppid
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPause(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows" && testEnv.DaemonInfo.Isolation == "process")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
name := "testeventpause"
|
||||
cID := container.Run(t, ctx, client, container.WithName(name))
|
||||
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
since := request.DaemonUnixTime(ctx, t, client, testEnv)
|
||||
|
||||
err := client.ContainerPause(ctx, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, inspect.State.Paused, true)
|
||||
|
||||
err = client.ContainerUnpause(ctx, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
until := request.DaemonUnixTime(ctx, t, client, testEnv)
|
||||
|
||||
messages, errs := client.Events(ctx, types.EventsOptions{
|
||||
Since: since,
|
||||
Until: until,
|
||||
Filters: filters.NewArgs(filters.Arg("container", name)),
|
||||
})
|
||||
assert.Equal(t, getEventActions(t, messages, errs), []string{"pause", "unpause"})
|
||||
}
|
||||
|
||||
func TestPauseFailsOnWindowsServerContainers(t *testing.T) {
|
||||
skip.If(t, (testEnv.DaemonInfo.OSType != "windows" || testEnv.DaemonInfo.Isolation != "process"))
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerPause(ctx, cID)
|
||||
testutil.ErrorContains(t, err, "cannot pause Windows Server Containers")
|
||||
}
|
||||
|
||||
func TestPauseStopPausedContainer(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerPause(ctx, cID)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = client.ContainerStop(ctx, cID, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
poll.WaitOn(t, containerIsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
|
||||
func getEventActions(t *testing.T, messages <-chan events.Message, errs <-chan error) []string {
|
||||
actions := []string{}
|
||||
for {
|
||||
select {
|
||||
case err := <-errs:
|
||||
assert.Equal(t, err == nil || err == io.EOF, true)
|
||||
return actions
|
||||
case e := <-messages:
|
||||
actions = append(actions, e.Status)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/icmd"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
@@ -25,23 +24,9 @@ func TestStopContainerWithRestartPolicyAlways(t *testing.T) {
|
||||
|
||||
names := []string{"verifyRestart1", "verifyRestart2"}
|
||||
for _, name := range names {
|
||||
resp, err := client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Cmd: []string{"false"},
|
||||
Image: "busybox",
|
||||
},
|
||||
&container.HostConfig{
|
||||
RestartPolicy: container.RestartPolicy{
|
||||
Name: "always",
|
||||
},
|
||||
},
|
||||
&network.NetworkingConfig{},
|
||||
name,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = client.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
|
||||
require.NoError(t, err)
|
||||
container.Run(t, ctx, client, container.WithName(name), container.WithCmd("false"), func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.RestartPolicy.Name = "always"
|
||||
})
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
@@ -65,25 +50,13 @@ func TestDeleteDevicemapper(t *testing.T) {
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
foo, err := client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Cmd: []string{"echo"},
|
||||
Image: "busybox",
|
||||
},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{},
|
||||
"foo",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
id := container.Run(t, ctx, client, container.WithName("foo"), container.WithCmd("echo"))
|
||||
|
||||
err = client.ContainerStart(ctx, foo.ID, types.ContainerStartOptions{})
|
||||
require.NoError(t, err)
|
||||
poll.WaitOn(t, containerIsStopped(ctx, client, id), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, foo.ID)
|
||||
inspect, err := client.ContainerInspect(ctx, id)
|
||||
require.NoError(t, err)
|
||||
|
||||
poll.WaitOn(t, containerIsStopped(ctx, client, foo.ID), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
deviceID := inspect.GraphDriver.Data["DeviceId"]
|
||||
|
||||
// Find pool name from device name
|
||||
@@ -94,7 +67,7 @@ func TestDeleteDevicemapper(t *testing.T) {
|
||||
result := icmd.RunCommand("dmsetup", "message", devicePool, "0", fmt.Sprintf("delete %s", deviceID))
|
||||
result.Assert(t, icmd.Success)
|
||||
|
||||
err = client.ContainerRemove(ctx, foo.ID, types.ContainerRemoveOptions{})
|
||||
err = client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package container // import "github.com/docker/docker/integration/container"
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -11,9 +10,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
@@ -31,44 +31,32 @@ func TestUpdateMemory(t *testing.T) {
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
c, err := client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Cmd: []string{"top"},
|
||||
Image: "busybox",
|
||||
},
|
||||
&container.HostConfig{
|
||||
Resources: container.Resources{
|
||||
Memory: 200 * 1024 * 1024,
|
||||
},
|
||||
},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
cID := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.Resources = containertypes.Resources{
|
||||
Memory: 200 * 1024 * 1024,
|
||||
}
|
||||
})
|
||||
|
||||
err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
|
||||
require.NoError(t, err)
|
||||
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
_, err = client.ContainerUpdate(ctx, c.ID, container.UpdateConfig{
|
||||
Resources: container.Resources{
|
||||
_, err := client.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{
|
||||
Resources: containertypes.Resources{
|
||||
Memory: 314572800,
|
||||
MemorySwap: 524288000,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, c.ID)
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, inspect.HostConfig.Memory, int64(314572800))
|
||||
assert.Equal(t, inspect.HostConfig.MemorySwap, int64(524288000))
|
||||
|
||||
body, err := getContainerSysFSValue(ctx, client, c.ID, "/sys/fs/cgroup/memory/memory.limit_in_bytes")
|
||||
body, err := getContainerSysFSValue(ctx, client, cID, "/sys/fs/cgroup/memory/memory.limit_in_bytes")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(body), "314572800")
|
||||
|
||||
body, err = getContainerSysFSValue(ctx, client, c.ID, "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes")
|
||||
body, err = getContainerSysFSValue(ctx, client, cID, "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(body), "524288000")
|
||||
}
|
||||
@@ -76,25 +64,11 @@ func TestUpdateMemory(t *testing.T) {
|
||||
func TestUpdateCPUQUota(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
c, err := client.ContainerCreate(ctx, &container.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"top"},
|
||||
}, nil, nil, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := client.ContainerRemove(ctx, c.ID, types.ContainerRemoveOptions{Force: true}); err != nil {
|
||||
panic(fmt.Sprintf("failed to clean up after test: %v", err))
|
||||
}
|
||||
}()
|
||||
|
||||
if err := client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
for _, test := range []struct {
|
||||
desc string
|
||||
@@ -105,15 +79,15 @@ func TestUpdateCPUQUota(t *testing.T) {
|
||||
{desc: "a lower value", update: 10000},
|
||||
{desc: "unset value", update: -1},
|
||||
} {
|
||||
if _, err := client.ContainerUpdate(ctx, c.ID, container.UpdateConfig{
|
||||
Resources: container.Resources{
|
||||
if _, err := client.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{
|
||||
Resources: containertypes.Resources{
|
||||
CPUQuota: test.update,
|
||||
},
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, c.ID)
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -122,7 +96,7 @@ func TestUpdateCPUQUota(t *testing.T) {
|
||||
t.Fatalf("quota not updated in the API, expected %d, got: %d", test.update, inspect.HostConfig.CPUQuota)
|
||||
}
|
||||
|
||||
execCreate, err := client.ContainerExecCreate(ctx, c.ID, types.ExecConfig{
|
||||
execCreate, err := client.ContainerExecCreate(ctx, cID, types.ExecConfig{
|
||||
Cmd: []string{"/bin/cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package request // import "github.com/docker/docker/integration/internal/request"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -49,3 +53,24 @@ func NewTLSAPIClient(t *testing.T, host, cacertPath, certPath, keyPath string) (
|
||||
}
|
||||
return client.NewClientWithOpts(client.WithHost(host), client.WithHTTPClient(httpClient))
|
||||
}
|
||||
|
||||
// daemonTime provides the current time on the daemon host
|
||||
func daemonTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
|
||||
if testEnv.IsLocalDaemon() {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
info, err := client.Info(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||
require.NoError(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 *testing.T, client client.APIClient, testEnv *environment.Execution) string {
|
||||
dt := daemonTime(ctx, t, client, testEnv)
|
||||
return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/swarm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -27,20 +27,15 @@ func TestDockerNetworkConnectAlias(t *testing.T) {
|
||||
Attachable: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Cmd: []string{"top"},
|
||||
Image: "busybox",
|
||||
},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{
|
||||
EndpointsConfig: map[string]*network.EndpointSettings{
|
||||
|
||||
container.Create(t, ctx, client, container.WithName("ng1"), func(c *container.TestContainerConfig) {
|
||||
c.NetworkingConfig = &network.NetworkingConfig{
|
||||
map[string]*network.EndpointSettings{
|
||||
name: {},
|
||||
},
|
||||
},
|
||||
"ng1",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
err = client.NetworkConnect(ctx, name, "ng1", &network.EndpointSettings{
|
||||
Aliases: []string{
|
||||
"aaa",
|
||||
@@ -56,20 +51,14 @@ func TestDockerNetworkConnectAlias(t *testing.T) {
|
||||
assert.Equal(t, len(ng1.NetworkSettings.Networks[name].Aliases), 2)
|
||||
assert.Equal(t, ng1.NetworkSettings.Networks[name].Aliases[0], "aaa")
|
||||
|
||||
_, err = client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Cmd: []string{"top"},
|
||||
Image: "busybox",
|
||||
},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{
|
||||
EndpointsConfig: map[string]*network.EndpointSettings{
|
||||
container.Create(t, ctx, client, container.WithName("ng2"), func(c *container.TestContainerConfig) {
|
||||
c.NetworkingConfig = &network.NetworkingConfig{
|
||||
map[string]*network.EndpointSettings{
|
||||
name: {},
|
||||
},
|
||||
},
|
||||
"ng2",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
err = client.NetworkConnect(ctx, name, "ng2", &network.EndpointSettings{
|
||||
Aliases: []string{
|
||||
"bbb",
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package session // import "github.com/docker/docker/integration/session"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package session // import "github.com/docker/docker/integration/session"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
req "github.com/docker/docker/integration-cli/request"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSessionCreate(t *testing.T) {
|
||||
skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild)
|
||||
|
||||
defer setupTest(t)()
|
||||
|
||||
res, body, err := req.Post("/session", func(r *http.Request) error {
|
||||
r.Header.Set("X-Docker-Expose-Session-Uuid", "testsessioncreate") // so we don't block default name if something else is using it
|
||||
r.Header.Set("Upgrade", "h2c")
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, body.Close())
|
||||
assert.Equal(t, res.StatusCode, http.StatusSwitchingProtocols)
|
||||
assert.Equal(t, res.Header.Get("Upgrade"), "h2c")
|
||||
}
|
||||
|
||||
func TestSessionCreateWithBadUpgrade(t *testing.T) {
|
||||
skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild)
|
||||
|
||||
res, body, err := req.Post("/session")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, res.StatusCode, http.StatusBadRequest)
|
||||
buf, err := req.ReadBody(body)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(buf), "no upgrade")
|
||||
|
||||
res, body, err = req.Post("/session", func(r *http.Request) error {
|
||||
r.Header.Set("Upgrade", "foo")
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, res.StatusCode, http.StatusBadRequest)
|
||||
buf, err = req.ReadBody(body)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(buf), "not supported")
|
||||
}
|
||||
@@ -7,10 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -20,22 +19,9 @@ func TestEvents(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
container, err := client.ContainerCreate(ctx,
|
||||
&container.Config{
|
||||
Image: "busybox",
|
||||
Tty: true,
|
||||
WorkingDir: "/root",
|
||||
Cmd: strslice.StrSlice([]string{"top"}),
|
||||
},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{},
|
||||
"foo",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
err = client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{})
|
||||
require.NoError(t, err)
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
id, err := client.ContainerExecCreate(ctx, container.ID,
|
||||
id, err := client.ContainerExecCreate(ctx, cID,
|
||||
types.ExecConfig{
|
||||
Cmd: strslice.StrSlice([]string{"echo", "hello"}),
|
||||
},
|
||||
@@ -43,7 +29,7 @@ func TestEvents(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
filters := filters.NewArgs(
|
||||
filters.Arg("container", container.ID),
|
||||
filters.Arg("container", cID),
|
||||
filters.Arg("event", "exec_die"),
|
||||
)
|
||||
msg, errors := client.Events(ctx, types.EventsOptions{
|
||||
@@ -61,7 +47,7 @@ func TestEvents(t *testing.T) {
|
||||
select {
|
||||
case m := <-msg:
|
||||
require.Equal(t, m.Type, "container")
|
||||
require.Equal(t, m.Actor.ID, container.ID)
|
||||
require.Equal(t, m.Actor.ID, cID)
|
||||
require.Equal(t, m.Action, "exec_die")
|
||||
require.Equal(t, m.Actor.Attributes["execID"], id.ID)
|
||||
require.Equal(t, m.Actor.Attributes["exitCode"], "0")
|
||||
|
||||
@@ -159,7 +159,7 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba
|
||||
return attachStdio(dio)
|
||||
}
|
||||
t, err := ctr.Task(ctx, attachIO)
|
||||
if err != nil && !errdefs.IsNotFound(errors.Cause(err)) {
|
||||
if err != nil && !containerderrors.IsNotFound(err) {
|
||||
return false, -1, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user