Merge pull request #512 from thaJeztah/18.03-backport-tests

[18.03] backport updates to tests, and fix empty LogPath with non-blocking logging mode
This commit is contained in:
Andrew Hsu
2018-04-17 14:56:29 -07:00
committed by GitHub
56 changed files with 1021 additions and 771 deletions
+1 -1
View File
@@ -142,7 +142,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 5e28dcaace5f7b70cbe44c313b7a3b288fa38916
ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f
# To run integration tests docker-pycreds is required.
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
+1 -1
View File
@@ -106,7 +106,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 5e28dcaace5f7b70cbe44c313b7a3b288fa38916
ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f
# To run integration tests docker-pycreds is required.
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
+1 -1
View File
@@ -104,7 +104,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 5e28dcaace5f7b70cbe44c313b7a3b288fa38916
ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f
# To run integration tests docker-pycreds is required.
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
+1 -1
View File
@@ -102,7 +102,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 5e28dcaace5f7b70cbe44c313b7a3b288fa38916
ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f
# To run integration tests docker-pycreds is required.
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
+1 -1
View File
@@ -96,7 +96,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT 5e28dcaace5f7b70cbe44c313b7a3b288fa38916
ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f
# To run integration tests docker-pycreds is required.
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
+3 -6
View File
@@ -38,7 +38,7 @@ import (
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
units "github.com/docker/go-units"
"github.com/docker/libnetwork"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/options"
@@ -391,6 +391,8 @@ func (container *Container) StartLogger() (logger.Logger, error) {
if err != nil {
return nil, err
}
container.LogPath = info.LogPath
}
l, err := initDriver(info)
@@ -974,11 +976,6 @@ func (container *Container) startLogging() error {
copier.Run()
container.LogDriver = l
// set LogPath field only for json-file logdriver
if jl, ok := l.(*jsonfilelog.JSONFileLogger); ok {
container.LogPath = jl.LogPath()
}
return nil
}
@@ -1,12 +1,17 @@
package container // import "github.com/docker/docker/container"
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/docker/docker/api/types/container"
swarmtypes "github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/daemon/logger/jsonfilelog"
"github.com/docker/docker/pkg/signal"
"github.com/stretchr/testify/require"
)
func TestContainerStopSignal(t *testing.T) {
@@ -66,3 +71,56 @@ func TestContainerSecretReferenceDestTarget(t *testing.T) {
t.Fatalf("expected secret dest %q; received %q", expected, d)
}
}
func TestContainerLogPathSetForJSONFileLogger(t *testing.T) {
containerRoot, err := ioutil.TempDir("", "TestContainerLogPathSetForJSONFileLogger")
require.NoError(t, err)
defer os.RemoveAll(containerRoot)
c := &Container{
Config: &container.Config{},
HostConfig: &container.HostConfig{
LogConfig: container.LogConfig{
Type: jsonfilelog.Name,
},
},
ID: "TestContainerLogPathSetForJSONFileLogger",
Root: containerRoot,
}
logger, err := c.StartLogger()
require.NoError(t, err)
defer logger.Close()
expectedLogPath, err := filepath.Abs(filepath.Join(containerRoot, fmt.Sprintf("%s-json.log", c.ID)))
require.NoError(t, err)
require.Equal(t, c.LogPath, expectedLogPath)
}
func TestContainerLogPathSetForRingLogger(t *testing.T) {
containerRoot, err := ioutil.TempDir("", "TestContainerLogPathSetForRingLogger")
require.NoError(t, err)
defer os.RemoveAll(containerRoot)
c := &Container{
Config: &container.Config{},
HostConfig: &container.HostConfig{
LogConfig: container.LogConfig{
Type: jsonfilelog.Name,
Config: map[string]string{
"mode": string(container.LogModeNonBlock),
},
},
},
ID: "TestContainerLogPathSetForRingLogger",
Root: containerRoot,
}
logger, err := c.StartLogger()
require.NoError(t, err)
defer logger.Close()
expectedLogPath, err := filepath.Abs(filepath.Join(containerRoot, fmt.Sprintf("%s-json.log", c.ID)))
require.NoError(t, err)
require.Equal(t, c.LogPath, expectedLogPath)
}
@@ -150,11 +150,6 @@ func ValidateLogOpt(cfg map[string]string) error {
return nil
}
// LogPath returns the location the given json logger logs to.
func (l *JSONFileLogger) LogPath() string {
return l.writer.LogPath()
}
// Close closes underlying file and signals all readers to stop.
func (l *JSONFileLogger) Close() error {
l.mu.Lock()
@@ -130,13 +130,6 @@ func rotate(name string, maxFiles int) error {
return nil
}
// LogPath returns the location the given writer logs to.
func (w *LogFile) LogPath() string {
w.mu.Lock()
defer w.mu.Unlock()
return w.f.Name()
}
// MaxFiles return maximum number of files
func (w *LogFile) MaxFiles() int {
return w.maxFiles
@@ -84,7 +84,7 @@ type DockerSuite struct {
}
func (s *DockerSuite) OnTimeout(c *check.C) {
if !testEnv.IsLocalDaemon() {
if testEnv.IsRemoteDaemon() {
return
}
path := filepath.Join(os.Getenv("DEST"), "docker.pid")
@@ -1,74 +0,0 @@
package main
import (
"encoding/json"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/integration-cli/request"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/go-check/check"
)
func (s *DockerSuite) TestEventsAPIEmptyOutput(c *check.C) {
type apiResp struct {
resp *http.Response
err error
}
chResp := make(chan *apiResp)
go func() {
resp, body, err := request.Get("/events")
body.Close()
chResp <- &apiResp{resp, err}
}()
select {
case r := <-chResp:
c.Assert(r.err, checker.IsNil)
c.Assert(r.resp.StatusCode, checker.Equals, http.StatusOK)
case <-time.After(3 * time.Second):
c.Fatal("timeout waiting for events api to respond, should have responded immediately")
}
}
func (s *DockerSuite) TestEventsAPIBackwardsCompatible(c *check.C) {
since := daemonTime(c).Unix()
ts := strconv.FormatInt(since, 10)
out := runSleepingContainer(c, "--name=foo", "-d")
containerID := strings.TrimSpace(out)
c.Assert(waitRun(containerID), checker.IsNil)
q := url.Values{}
q.Set("since", ts)
_, body, err := request.Get("/events?" + q.Encode())
c.Assert(err, checker.IsNil)
defer body.Close()
dec := json.NewDecoder(body)
var containerCreateEvent *jsonmessage.JSONMessage
for {
var event jsonmessage.JSONMessage
if err := dec.Decode(&event); err != nil {
if err == io.EOF {
break
}
c.Fatal(err)
}
if event.Status == "create" && event.ID == containerID {
containerCreateEvent = &event
break
}
}
c.Assert(containerCreateEvent, checker.Not(checker.IsNil))
c.Assert(containerCreateEvent.Status, checker.Equals, "create")
c.Assert(containerCreateEvent.ID, checker.Equals, containerID)
c.Assert(containerCreateEvent.From, checker.Equals, "busybox")
}
@@ -1,103 +0,0 @@
package main
import (
"fmt"
"path/filepath"
"strings"
"time"
"github.com/docker/docker/api/types/filters"
volumetypes "github.com/docker/docker/api/types/volume"
"github.com/docker/docker/client"
"github.com/docker/docker/integration-cli/checker"
"github.com/go-check/check"
"golang.org/x/net/context"
)
func (s *DockerSuite) TestVolumesAPIList(c *check.C) {
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
cid, _ := dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "busybox")
cli, err := client.NewEnvClient()
c.Assert(err, checker.IsNil)
defer cli.Close()
container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
c.Assert(err, checker.IsNil)
vname := container.Mounts[0].Name
volumes, err := cli.VolumeList(context.Background(), filters.Args{})
c.Assert(err, checker.IsNil)
found := false
for _, vol := range volumes.Volumes {
if vol.Name == vname {
found = true
break
}
}
c.Assert(found, checker.Equals, true)
}
func (s *DockerSuite) TestVolumesAPICreate(c *check.C) {
config := volumetypes.VolumesCreateBody{
Name: "test",
}
cli, err := client.NewEnvClient()
c.Assert(err, checker.IsNil)
defer cli.Close()
vol, err := cli.VolumeCreate(context.Background(), config)
c.Assert(err, check.IsNil)
c.Assert(filepath.Base(filepath.Dir(vol.Mountpoint)), checker.Equals, config.Name)
}
func (s *DockerSuite) TestVolumesAPIRemove(c *check.C) {
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
cid, _ := dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "--name=test", "busybox")
cli, err := client.NewEnvClient()
c.Assert(err, checker.IsNil)
defer cli.Close()
container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
c.Assert(err, checker.IsNil)
vname := container.Mounts[0].Name
err = cli.VolumeRemove(context.Background(), vname, false)
c.Assert(err.Error(), checker.Contains, "volume is in use")
dockerCmd(c, "rm", "-f", "test")
err = cli.VolumeRemove(context.Background(), vname, false)
c.Assert(err, checker.IsNil)
}
func (s *DockerSuite) TestVolumesAPIInspect(c *check.C) {
config := volumetypes.VolumesCreateBody{
Name: "test",
}
// sampling current time minus a minute so to now have false positive in case of delays
now := time.Now().Truncate(time.Minute)
cli, err := client.NewEnvClient()
c.Assert(err, checker.IsNil)
defer cli.Close()
_, err = cli.VolumeCreate(context.Background(), config)
c.Assert(err, check.IsNil)
vol, err := cli.VolumeInspect(context.Background(), config.Name)
c.Assert(err, checker.IsNil)
c.Assert(vol.Name, checker.Equals, config.Name)
// comparing CreatedAt field time for the new volume to now. Removing a minute from both to avoid false positive
testCreatedAt, err := time.Parse(time.RFC3339, strings.TrimSpace(vol.CreatedAt))
c.Assert(err, check.IsNil)
testCreatedAt = testCreatedAt.Truncate(time.Minute)
if !testCreatedAt.Equal(now) {
c.Assert(fmt.Errorf("Time Volume is CreatedAt not equal to current time"), check.NotNil)
}
}
@@ -1,68 +0,0 @@
// +build !windows
package main
import (
"encoding/json"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/integration-cli/checker"
"github.com/go-check/check"
)
func (s *DockerSwarmSuite) TestConfigInspect(c *check.C) {
d := s.AddDaemon(c, true, true)
testName := "test_config"
id := d.CreateConfig(c, swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: testName,
},
Data: []byte("TESTINGDATA"),
})
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id))
config := d.GetConfig(c, id)
c.Assert(config.Spec.Name, checker.Equals, testName)
out, err := d.Cmd("config", "inspect", testName)
c.Assert(err, checker.IsNil, check.Commentf(out))
var configs []swarm.Config
c.Assert(json.Unmarshal([]byte(out), &configs), checker.IsNil)
c.Assert(configs, checker.HasLen, 1)
}
func (s *DockerSwarmSuite) TestConfigInspectMultiple(c *check.C) {
d := s.AddDaemon(c, true, true)
testNames := []string{
"test0",
"test1",
}
for _, n := range testNames {
id := d.CreateConfig(c, swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: n,
},
Data: []byte("TESTINGDATA"),
})
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id))
config := d.GetConfig(c, id)
c.Assert(config.Spec.Name, checker.Equals, n)
}
args := []string{
"config",
"inspect",
}
args = append(args, testNames...)
out, err := d.Cmd(args...)
c.Assert(err, checker.IsNil, check.Commentf(out))
var configs []swarm.Config
c.Assert(json.Unmarshal([]byte(out), &configs), checker.IsNil)
c.Assert(configs, checker.HasLen, 2)
}
@@ -9,25 +9,8 @@ import (
"github.com/gotestyourself/gotestyourself/icmd"
)
// export an image and try to import it into a new one
func (s *DockerSuite) TestExportContainerAndImportImage(c *check.C) {
testRequires(c, DaemonIsLinux)
containerID := "testexportcontainerandimportimage"
dockerCmd(c, "run", "--name", containerID, "busybox", "true")
out, _ := dockerCmd(c, "export", containerID)
result := icmd.RunCmd(icmd.Cmd{
Command: []string{dockerBinary, "import", "-", "repo/testexp:v1"},
Stdin: strings.NewReader(out),
})
result.Assert(c, icmd.Success)
cleanedImageID := strings.TrimSpace(result.Combined())
c.Assert(cleanedImageID, checker.Not(checker.Equals), "", check.Commentf("output should have been an image id"))
}
// TODO: Move this test to docker/cli, as it is essentially the same test
// as TestExportContainerAndImportImage except output to a file.
// Used to test output flag in the export command
func (s *DockerSuite) TestExportContainerWithOutputAndImportImage(c *check.C) {
testRequires(c, DaemonIsLinux)
@@ -1,87 +0,0 @@
package main
import (
"io/ioutil"
"os"
"github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/integration-cli/cli/build"
"github.com/go-check/check"
)
func (s *DockerSuite) TestRmContainerWithRemovedVolume(c *check.C) {
testRequires(c, SameHostDaemon)
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
tempDir, err := ioutil.TempDir("", "test-rm-container-with-removed-volume-")
if err != nil {
c.Fatalf("failed to create temporary directory: %s", tempDir)
}
defer os.RemoveAll(tempDir)
dockerCmd(c, "run", "--name", "losemyvolumes", "-v", tempDir+":"+prefix+slash+"test", "busybox", "true")
err = os.RemoveAll(tempDir)
c.Assert(err, check.IsNil)
dockerCmd(c, "rm", "-v", "losemyvolumes")
}
func (s *DockerSuite) TestRmContainerWithVolume(c *check.C) {
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
dockerCmd(c, "run", "--name", "foo", "-v", prefix+slash+"srv", "busybox", "true")
dockerCmd(c, "rm", "-v", "foo")
}
func (s *DockerSuite) TestRmContainerRunning(c *check.C) {
createRunningContainer(c, "foo")
res, _, err := dockerCmdWithError("rm", "foo")
c.Assert(err, checker.NotNil, check.Commentf("Expected error, can't rm a running container"))
c.Assert(res, checker.Contains, "cannot remove a running container")
}
func (s *DockerSuite) TestRmContainerForceRemoveRunning(c *check.C) {
createRunningContainer(c, "foo")
// Stop then remove with -f
dockerCmd(c, "rm", "-f", "foo")
}
func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
dockerfile1 := `FROM busybox:latest
ENTRYPOINT ["true"]`
img := "test-container-orphaning"
dockerfile2 := `FROM busybox:latest
ENTRYPOINT ["true"]
MAINTAINER Integration Tests`
// build first dockerfile
buildImageSuccessfully(c, img, build.WithDockerfile(dockerfile1))
img1 := getIDByName(c, img)
// run container on first image
dockerCmd(c, "run", img)
// rebuild dockerfile with a small addition at the end
buildImageSuccessfully(c, img, build.WithDockerfile(dockerfile2))
// try to remove the image, should not error out.
out, _, err := dockerCmdWithError("rmi", img)
c.Assert(err, check.IsNil, check.Commentf("Expected to removing the image, but failed: %s", out))
// check if we deleted the first image
out, _ = dockerCmd(c, "images", "-q", "--no-trunc")
c.Assert(out, checker.Contains, img1, check.Commentf("Orphaned container (could not find %q in docker images): %s", img1, out))
}
func (s *DockerSuite) TestRmInvalidContainer(c *check.C) {
out, _, err := dockerCmdWithError("rm", "unknown")
c.Assert(err, checker.NotNil, check.Commentf("Expected error on rm unknown container, got none"))
c.Assert(out, checker.Contains, "No such container")
}
func createRunningContainer(c *check.C, name string) {
runSleepingContainer(c, "-dt", "--name", name)
}
@@ -12,45 +12,6 @@ import (
"github.com/go-check/check"
)
func (s *DockerSwarmSuite) TestSecretCreate(c *check.C) {
d := s.AddDaemon(c, true, true)
testName := "test_secret"
id := d.CreateSecret(c, swarm.SecretSpec{
Annotations: swarm.Annotations{
Name: testName,
},
Data: []byte("TESTINGDATA"),
})
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
secret := d.GetSecret(c, id)
c.Assert(secret.Spec.Name, checker.Equals, testName)
}
func (s *DockerSwarmSuite) TestSecretCreateWithLabels(c *check.C) {
d := s.AddDaemon(c, true, true)
testName := "test_secret"
id := d.CreateSecret(c, swarm.SecretSpec{
Annotations: swarm.Annotations{
Name: testName,
Labels: map[string]string{
"key1": "value1",
"key2": "value2",
},
},
Data: []byte("TESTINGDATA"),
})
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
secret := d.GetSecret(c, id)
c.Assert(secret.Spec.Name, checker.Equals, testName)
c.Assert(len(secret.Spec.Labels), checker.Equals, 2)
c.Assert(secret.Spec.Labels["key1"], checker.Equals, "value1")
c.Assert(secret.Spec.Labels["key2"], checker.Equals, "value2")
}
// Test case for 28884
func (s *DockerSwarmSuite) TestSecretCreateResolve(c *check.C) {
d := s.AddDaemon(c, true, true)
@@ -1,45 +0,0 @@
// +build !windows
package main
import (
"encoding/json"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/integration-cli/checker"
"github.com/go-check/check"
)
func (s *DockerSwarmSuite) TestSecretInspectMultiple(c *check.C) {
d := s.AddDaemon(c, true, true)
testNames := []string{
"test0",
"test1",
}
for _, n := range testNames {
id := d.CreateSecret(c, swarm.SecretSpec{
Annotations: swarm.Annotations{
Name: n,
},
Data: []byte("TESTINGDATA"),
})
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
secret := d.GetSecret(c, id)
c.Assert(secret.Spec.Name, checker.Equals, n)
}
args := []string{
"secret",
"inspect",
}
args = append(args, testNames...)
out, err := d.Cmd(args...)
c.Assert(err, checker.IsNil, check.Commentf(out))
var secrets []swarm.Secret
c.Assert(json.Unmarshal([]byte(out), &secrets), checker.IsNil)
c.Assert(secrets, checker.HasLen, 2)
}
@@ -11,41 +11,6 @@ import (
"github.com/go-check/check"
)
func (s *DockerSwarmSuite) TestServiceUpdatePort(c *check.C) {
d := s.AddDaemon(c, true, true)
serviceName := "TestServiceUpdatePort"
serviceArgs := append([]string{"service", "create", "--detach", "--no-resolve-image", "--name", serviceName, "-p", "8080:8081", defaultSleepImage}, sleepCommandForDaemonPlatform()...)
// Create a service with a port mapping of 8080:8081.
out, err := d.Cmd(serviceArgs...)
c.Assert(err, checker.IsNil)
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
// Update the service: changed the port mapping from 8080:8081 to 8082:8083.
_, err = d.Cmd("service", "update", "--detach", "--publish-add", "8082:8083", "--publish-rm", "8081", serviceName)
c.Assert(err, checker.IsNil)
// Inspect the service and verify port mapping
expected := []swarm.PortConfig{
{
Protocol: "tcp",
PublishedPort: 8082,
TargetPort: 8083,
PublishMode: "ingress",
},
}
out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.EndpointSpec.Ports }}", serviceName)
c.Assert(err, checker.IsNil)
var portConfig []swarm.PortConfig
if err := json.Unmarshal([]byte(out), &portConfig); err != nil {
c.Fatalf("invalid JSON in inspect result: %v (%s)", err, out)
}
c.Assert(portConfig, checker.DeepEquals, expected)
}
func (s *DockerSwarmSuite) TestServiceUpdateLabel(c *check.C) {
d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name=test", "busybox", "top")
@@ -42,6 +42,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
master := "dm-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use
createMasterDummy(c, master)
// cleanup the master interface that also collects the slave dev
defer deleteInterface(c, master)
// create a network specifying the desired sub-interface name
dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.60", "dm-persist")
assertNwIsAvailable(c, "dm-persist")
@@ -49,8 +51,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
s.d.Restart(c)
// verify network is recreated from persistence
assertNwIsAvailable(c, "dm-persist")
// cleanup the master interface that also collects the slave dev
deleteInterface(c, "dm-dummy0")
}
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
@@ -60,6 +60,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
master := "di-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use
createMasterDummy(c, master)
// cleanup the master interface that also collects the slave dev
defer deleteInterface(c, master)
// create a network specifying the desired sub-interface name
dockerCmd(c, "network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.70", "di-persist")
assertNwIsAvailable(c, "di-persist")
@@ -67,8 +69,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
s.d.Restart(c)
// verify network is recreated from persistence
assertNwIsAvailable(c, "di-persist")
// cleanup the master interface that also collects the slave dev
deleteInterface(c, "di-dummy0")
}
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
@@ -78,11 +78,11 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
master := "dm-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use
createMasterDummy(c, master)
// cleanup the master interface which also collects the slave dev
defer deleteInterface(c, master)
// create a network specifying the desired sub-interface name
dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.50", "dm-subinterface")
assertNwIsAvailable(c, "dm-subinterface")
// cleanup the master interface which also collects the slave dev
deleteInterface(c, "dm-dummy0")
}
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
@@ -92,11 +92,11 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
master := "di-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use
createMasterDummy(c, master)
// cleanup the master interface which also collects the slave dev
defer deleteInterface(c, master)
// create a network specifying the desired sub-interface name
dockerCmd(c, "network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.60", "di-subinterface")
assertNwIsAvailable(c, "di-subinterface")
// cleanup the master interface which also collects the slave dev
deleteInterface(c, "di-dummy0")
}
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
@@ -105,6 +105,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
// master dummy interface 'dm' abbreviation represents 'docker macvlan'
master := "dm-dummy0"
createMasterDummy(c, master)
// cleanup the master interface which also collects the slave dev
defer deleteInterface(c, master)
createVlanInterface(c, master, "dm-dummy0.40", "40")
// create a network using an existing parent interface
dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.40", "dm-subinterface")
@@ -113,8 +115,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
out, _, err := dockerCmdWithError("network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.40", "dm-parent-net-overlap")
// verify that the overlap returns an error
c.Assert(err, check.NotNil, check.Commentf(out))
// cleanup the master interface which also collects the slave dev
deleteInterface(c, "dm-dummy0")
}
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
@@ -123,6 +123,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
master := "di-dummy0"
createMasterDummy(c, master)
// cleanup the master interface which also collects the slave dev
defer deleteInterface(c, master)
createVlanInterface(c, master, "di-dummy0.30", "30")
// create a network using an existing parent interface
dockerCmd(c, "network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.30", "di-subinterface")
@@ -131,8 +133,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
out, _, err := dockerCmdWithError("network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.30", "di-parent-net-overlap")
// verify that the overlap returns an error
c.Assert(err, check.NotNil, check.Commentf(out))
// cleanup the master interface which also collects the slave dev
deleteInterface(c, "di-dummy0")
}
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) {
@@ -471,6 +471,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
netName := "dm-parent-exists"
createMasterDummy(c, "dm-dummy0")
defer deleteInterface(c, "dm-dummy0")
//out, err := createVlanInterface(c, "dm-parent", "dm-slave", "macvlan", "bridge")
// create a network using an existing parent interface
dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0", netName)
@@ -480,7 +481,6 @@ func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
assertNwNotAvailable(c, netName)
// verify the network delete did not delete the predefined link
linkExists(c, "dm-dummy0")
deleteInterface(c, "dm-dummy0")
}
func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
@@ -488,6 +488,8 @@ func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
netName := "dm-subinterface"
createMasterDummy(c, "dm-dummy0")
// delete the parent interface which also collects the slave
defer deleteInterface(c, "dm-dummy0")
createVlanInterface(c, "dm-dummy0", "dm-dummy0.20", "20")
// create a network using an existing parent interface
dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.20", netName)
@@ -510,8 +512,6 @@ func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
assertNwNotAvailable(c, netName)
// verify the network delete did not delete the predefined sub-interface
linkExists(c, "dm-dummy0.20")
// delete the parent interface which also collects the slave
deleteInterface(c, "dm-dummy0")
}
func createMasterDummy(c *check.C, master string) {
@@ -2,6 +2,7 @@ package config
import (
"bytes"
"encoding/json"
"sort"
"testing"
"time"
@@ -327,3 +328,27 @@ func waitAndAssert(t *testing.T, timeout time.Duration, f func(*testing.T) bool)
time.Sleep(100 * time.Millisecond)
}
}
func TestConfigInspect(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
defer setupTest(t)()
d := swarm.NewSwarm(t, testEnv)
defer d.Stop(t)
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
require.NoError(t, err)
ctx := context.Background()
testName := t.Name()
configID := createConfig(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
insp, body, err := client.ConfigInspectWithRaw(ctx, configID)
require.NoError(t, err)
assert.Equal(t, insp.Spec.Name, testName)
var config swarmtypes.Config
err = json.Unmarshal(body, &config)
require.NoError(t, err)
assert.Equal(t, config, insp)
}
@@ -9,8 +9,9 @@ import (
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/integration-cli/daemon"
"github.com/docker/docker/integration/internal/container"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"golang.org/x/sys/unix"
)
@@ -26,6 +27,7 @@ import (
// the container process, then start dockerd back up and attempt to start the
// container again.
func TestContainerStartOnDaemonRestart(t *testing.T) {
skip.If(t, testEnv.IsRemoteDaemon(), "cannot start daemon on remote test run")
t.Parallel()
d := daemon.New(t, "", "dockerd", daemon.Config{})
@@ -36,22 +38,14 @@ func TestContainerStartOnDaemonRestart(t *testing.T) {
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{})
cID := container.Create(t, ctx, client)
defer client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
err = client.ContainerStart(ctx, cID, types.ContainerStartOptions{})
assert.NoError(t, err, "error starting test container")
inspect, err := client.ContainerInspect(ctx, c.ID)
inspect, err := client.ContainerInspect(ctx, cID)
assert.NoError(t, err, "error getting inspect data")
ppid := getContainerdShimPid(t, inspect)
@@ -67,7 +61,7 @@ func TestContainerStartOnDaemonRestart(t *testing.T) {
d.Start(t, "--iptables=false")
err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
err = client.ContainerStart(ctx, cID, types.ContainerStartOptions{})
assert.NoError(t, err, "failed to start test container")
}
@@ -10,13 +10,11 @@ import (
"github.com/docker/docker/integration/internal/request"
"github.com/docker/docker/pkg/archive"
"github.com/gotestyourself/gotestyourself/poll"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// ensure that an added file shows up in docker diff
func TestDiffFilenameShownInOutput(t *testing.T) {
func TestDiff(t *testing.T) {
defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()
@@ -27,72 +25,19 @@ func TestDiffFilenameShownInOutput(t *testing.T) {
// it will take a few seconds to exit. Also there's no way in Windows to
// differentiate between an Add or a Modify, and all files are under
// a "Files/" prefix.
lookingFor := containertypes.ContainerChangeResponseItem{Kind: archive.ChangeAdd, Path: "/foo/bar"}
if testEnv.OSType == "windows" {
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(60*time.Second))
lookingFor = containertypes.ContainerChangeResponseItem{Kind: archive.ChangeModify, Path: "Files/foo/bar"}
expected := []containertypes.ContainerChangeResponseItem{
{Kind: archive.ChangeAdd, Path: "/foo"},
{Kind: archive.ChangeAdd, Path: "/foo/bar"},
}
items, err := client.ContainerDiff(ctx, cID)
require.NoError(t, err)
assert.Contains(t, items, lookingFor)
}
// test to ensure GH #3840 doesn't occur any more
func TestDiffEnsureInitLayerFilesAreIgnored(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()
// this is a list of files which shouldn't show up in `docker diff`
initLayerFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerenv"}
containerCount := 5
// we might not run into this problem from the first run, so start a few containers
for i := 0; i < containerCount; i++ {
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", `echo foo > /root/bar`))
items, err := client.ContainerDiff(ctx, cID)
require.NoError(t, err)
for _, item := range items {
assert.NotContains(t, initLayerFiles, item.Path)
if testEnv.OSType == "windows" {
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(60*time.Second))
expected = []containertypes.ContainerChangeResponseItem{
{Kind: archive.ChangeModify, Path: "Files/foo"},
{Kind: archive.ChangeModify, Path: "Files/foo/bar"},
}
}
}
func TestDiffEnsureDefaultDevs(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, container.WithCmd("sleep", "0"))
items, err := client.ContainerDiff(ctx, cID)
require.NoError(t, err)
expected := []containertypes.ContainerChangeResponseItem{
{Kind: archive.ChangeModify, Path: "/dev"},
{Kind: archive.ChangeAdd, Path: "/dev/full"}, // busybox
{Kind: archive.ChangeModify, Path: "/dev/ptmx"}, // libcontainer
{Kind: archive.ChangeAdd, Path: "/dev/mqueue"},
{Kind: archive.ChangeAdd, Path: "/dev/kmsg"},
{Kind: archive.ChangeAdd, Path: "/dev/fd"},
{Kind: archive.ChangeAdd, Path: "/dev/ptmx"},
{Kind: archive.ChangeAdd, Path: "/dev/null"},
{Kind: archive.ChangeAdd, Path: "/dev/random"},
{Kind: archive.ChangeAdd, Path: "/dev/stdout"},
{Kind: archive.ChangeAdd, Path: "/dev/stderr"},
{Kind: archive.ChangeAdd, Path: "/dev/tty1"},
{Kind: archive.ChangeAdd, Path: "/dev/stdin"},
{Kind: archive.ChangeAdd, Path: "/dev/tty"},
{Kind: archive.ChangeAdd, Path: "/dev/urandom"},
}
for _, item := range items {
assert.Contains(t, expected, item)
}
assert.Equal(t, expected, items)
}
@@ -0,0 +1,53 @@
package container // import "github.com/docker/docker/integration/container"
import (
"context"
"encoding/json"
"testing"
"time"
"github.com/docker/docker/api/types"
"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/pkg/jsonmessage"
"github.com/gotestyourself/gotestyourself/poll"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// export an image and try to import it into a new one
func TestExportContainerAndImportImage(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, container.WithCmd("true"))
poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
reference := "repo/testexp:v1"
exportResp, err := client.ContainerExport(ctx, cID)
require.NoError(t, err)
importResp, err := client.ImageImport(ctx, types.ImageImportSource{
Source: exportResp,
SourceName: "-",
}, reference, types.ImageImportOptions{})
require.NoError(t, err)
// If the import is successfully, then the message output should contain
// the image ID and match with the output from `docker images`.
dec := json.NewDecoder(importResp)
var jm jsonmessage.JSONMessage
err = dec.Decode(&jm)
require.NoError(t, err)
images, err := client.ImageList(ctx, types.ImageListOptions{
Filters: filters.NewArgs(filters.Arg("reference", reference)),
})
require.NoError(t, err)
assert.Equal(t, jm.Status, images[0].ID)
}
@@ -30,7 +30,7 @@ func TestInspectCpusetInConfigPre120(t *testing.T) {
c.HostConfig.Resources.CpusetCpus = "0"
},
)
poll.WaitOn(t, containerIsInState(ctx, client, name, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, name, "exited"), poll.WithDelay(100*time.Millisecond))
_, body, err := client.ContainerInspectWithRaw(ctx, name, false)
require.NoError(t, err)
@@ -40,9 +40,9 @@ func TestInspectCpusetInConfigPre120(t *testing.T) {
require.NoError(t, err, "unable to unmarshal body for version 1.19: %s", err)
config, ok := inspectJSON["Config"]
assert.Equal(t, ok, true, "Unable to find 'Config'")
assert.Equal(t, true, ok, "Unable to find 'Config'")
cfg := config.(map[string]interface{})
_, ok = cfg["Cpuset"]
assert.Equal(t, ok, true, "API version 1.19 expected to include Cpuset in 'Config'")
assert.Equal(t, true, ok, "API version 1.19 expected to include Cpuset in 'Config'")
}
@@ -23,11 +23,11 @@ func TestKillContainerInvalidSignal(t *testing.T) {
err := client.ContainerKill(ctx, id, "0")
require.EqualError(t, err, "Error response from daemon: Invalid signal: 0")
poll.WaitOn(t, containerIsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
err = client.ContainerKill(ctx, id, "SIG42")
require.EqualError(t, err, "Error response from daemon: Invalid signal: SIG42")
poll.WaitOn(t, containerIsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
}
func TestKillContainer(t *testing.T) {
@@ -64,7 +64,7 @@ func TestKillContainer(t *testing.T) {
err := client.ContainerKill(ctx, id, tc.signal)
require.NoError(t, err)
poll.WaitOn(t, containerIsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
})
}
}
@@ -104,7 +104,7 @@ func TestKillWithStopSignalAndRestartPolicies(t *testing.T) {
err := client.ContainerKill(ctx, id, "TERM")
require.NoError(t, err)
poll.WaitOn(t, containerIsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
})
}
}
@@ -141,11 +141,11 @@ func TestKillDifferentUserContainer(t *testing.T) {
id := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
c.Config.User = "daemon"
})
poll.WaitOn(t, containerIsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerKill(ctx, id, "SIGKILL")
require.NoError(t, err)
poll.WaitOn(t, containerIsInState(ctx, client, id, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, id, "exited"), poll.WithDelay(100*time.Millisecond))
}
func TestInspectOomKilledTrue(t *testing.T) {
@@ -155,16 +155,15 @@ func TestInspectOomKilledTrue(t *testing.T) {
ctx := context.Background()
client := request.NewAPIClient(t)
name := "testoomkilled"
cID := container.Run(t, ctx, client, container.WithName(name), container.WithCmd("sh", "-c", "x=a; while true; do x=$x$x$x$x; done"), func(c *container.TestContainerConfig) {
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", "x=a; while true; do x=$x$x$x$x; done"), func(c *container.TestContainerConfig) {
c.HostConfig.Resources.Memory = 32 * 1024 * 1024
})
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.State.OOMKilled, true)
assert.Equal(t, true, inspect.State.OOMKilled)
}
func TestInspectOomKilledFalse(t *testing.T) {
@@ -174,12 +173,11 @@ func TestInspectOomKilledFalse(t *testing.T) {
ctx := context.Background()
client := request.NewAPIClient(t)
name := "testoomkilled"
cID := container.Run(t, ctx, client, container.WithName(name), container.WithCmd("sh", "-c", "echo hello world"))
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", "echo hello world"))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.State.OOMKilled, false)
assert.Equal(t, false, inspect.State.OOMKilled)
}
@@ -1,26 +1,22 @@
package container // import "github.com/docker/docker/integration/container"
import (
"bytes"
"context"
"io/ioutil"
"os"
"testing"
"time"
"github.com/docker/docker/api/types"
"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/pkg/stdcopy"
"github.com/gotestyourself/gotestyourself/poll"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLinksEtcHostsContentMatch(t *testing.T) {
skip.If(t, !testEnv.IsLocalDaemon())
skip.If(t, testEnv.IsRemoteDaemon())
hosts, err := ioutil.ReadFile("/etc/hosts")
skip.If(t, os.IsNotExist(err))
@@ -29,21 +25,13 @@ func TestLinksEtcHostsContentMatch(t *testing.T) {
client := request.NewAPIClient(t)
ctx := context.Background()
cID := container.Run(t, ctx, client, container.WithCmd("cat", "/etc/hosts"), container.WithNetworkMode("host"))
poll.WaitOn(t, containerIsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
body, err := client.ContainerLogs(ctx, cID, types.ContainerLogsOptions{
ShowStdout: true,
})
cID := container.Run(t, ctx, client, container.WithNetworkMode("host"))
res, err := container.Exec(ctx, client, cID, []string{"cat", "/etc/hosts"})
require.NoError(t, err)
defer body.Close()
require.Empty(t, res.Stderr())
require.Equal(t, 0, res.ExitCode)
var b bytes.Buffer
_, err = stdcopy.StdCopy(&b, ioutil.Discard, body)
require.NoError(t, err)
assert.Equal(t, string(hosts), b.String())
assert.Equal(t, string(hosts), res.Stdout())
}
func TestLinksContainerNames(t *testing.T) {
@@ -20,7 +20,6 @@ func TestLogsFollowTailEmpty(t *testing.T) {
ctx := context.Background()
id := container.Run(t, ctx, client, container.WithCmd("sleep", "100000"))
defer client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{Force: true})
logs, err := client.ContainerLogs(ctx, id, types.ContainerLogsOptions{ShowStdout: true, Tail: "2"})
if logs != nil {
@@ -23,6 +23,7 @@ import (
)
func TestContainerShmNoLeak(t *testing.T) {
skip.If(t, testEnv.IsRemoteDaemon(), "cannot start daemon on remote test run")
t.Parallel()
d := daemon.New(t, "docker", "dockerd", daemon.Config{})
client, err := d.NewClient()
@@ -94,7 +95,7 @@ func TestContainerShmNoLeak(t *testing.T) {
func TestContainerNetworkMountsNoChown(t *testing.T) {
// chown only applies to Linux bind mounted volumes; must be same host to verify
skip.If(t, testEnv.DaemonInfo.OSType != "linux" || !testEnv.IsLocalDaemon())
skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon())
defer setupTest(t)()
@@ -22,7 +22,7 @@ import (
)
func TestNetworkNat(t *testing.T) {
skip.If(t, !testEnv.IsLocalDaemon())
skip.If(t, testEnv.IsRemoteDaemon())
defer setupTest(t)()
@@ -36,11 +36,11 @@ func TestNetworkNat(t *testing.T) {
data, err := ioutil.ReadAll(conn)
require.NoError(t, err)
assert.Equal(t, strings.TrimSpace(string(data)), msg)
assert.Equal(t, msg, strings.TrimSpace(string(data)))
}
func TestNetworkLocalhostTCPNat(t *testing.T) {
skip.If(t, !testEnv.IsLocalDaemon())
skip.If(t, testEnv.IsRemoteDaemon())
defer setupTest(t)()
@@ -53,11 +53,11 @@ func TestNetworkLocalhostTCPNat(t *testing.T) {
data, err := ioutil.ReadAll(conn)
require.NoError(t, err)
assert.Equal(t, strings.TrimSpace(string(data)), msg)
assert.Equal(t, msg, strings.TrimSpace(string(data)))
}
func TestNetworkLoopbackNat(t *testing.T) {
skip.If(t, !testEnv.IsLocalDaemon())
skip.If(t, testEnv.IsRemoteDaemon())
msg := "it works"
startServerContainer(t, msg, 8080)
@@ -69,7 +69,7 @@ func TestNetworkLoopbackNat(t *testing.T) {
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", fmt.Sprintf("stty raw && nc -w 5 %s 8080", endpoint.String())), container.WithTty(true), container.WithNetworkMode("container:server"))
poll.WaitOn(t, containerIsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
body, err := client.ContainerLogs(ctx, cID, types.ContainerLogsOptions{
ShowStdout: true,
@@ -81,7 +81,7 @@ func TestNetworkLoopbackNat(t *testing.T) {
_, err = io.Copy(&b, body)
require.NoError(t, err)
assert.Equal(t, strings.TrimSpace(b.String()), msg)
assert.Equal(t, msg, strings.TrimSpace(b.String()))
}
func startServerContainer(t *testing.T, msg string, port int) string {
@@ -98,7 +98,7 @@ func startServerContainer(t *testing.T, msg string, port int) string {
}
})
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
return cID
}
@@ -109,7 +109,7 @@ func getExternalAddress(t *testing.T) net.IP {
ifaceAddrs, err := iface.Addrs()
require.NoError(t, err)
assert.NotEqual(t, len(ifaceAddrs), 0)
assert.NotEqual(t, 0, len(ifaceAddrs))
ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String())
require.NoError(t, err)
@@ -25,20 +25,19 @@ func TestPause(t *testing.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))
cID := container.Run(t, ctx, client)
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
since := request.DaemonUnixTime(ctx, t, client, testEnv)
err := client.ContainerPause(ctx, name)
err := client.ContainerPause(ctx, cID)
require.NoError(t, err)
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.State.Paused, true)
assert.Equal(t, true, inspect.State.Paused)
err = client.ContainerUnpause(ctx, name)
err = client.ContainerUnpause(ctx, cID)
require.NoError(t, err)
until := request.DaemonUnixTime(ctx, t, client, testEnv)
@@ -46,9 +45,9 @@ func TestPause(t *testing.T) {
messages, errs := client.Events(ctx, types.EventsOptions{
Since: since,
Until: until,
Filters: filters.NewArgs(filters.Arg("container", name)),
Filters: filters.NewArgs(filters.Arg("container", cID)),
})
assert.Equal(t, getEventActions(t, messages, errs), []string{"pause", "unpause"})
assert.Equal(t, []string{"pause", "unpause"}, getEventActions(t, messages, errs))
}
func TestPauseFailsOnWindowsServerContainers(t *testing.T) {
@@ -59,7 +58,7 @@ func TestPauseFailsOnWindowsServerContainers(t *testing.T) {
ctx := context.Background()
cID := container.Run(t, ctx, client)
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerPause(ctx, cID)
testutil.ErrorContains(t, err, "cannot pause Windows Server Containers")
@@ -73,7 +72,7 @@ func TestPauseStopPausedContainer(t *testing.T) {
ctx := context.Background()
cID := container.Run(t, ctx, client)
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerPause(ctx, cID)
require.NoError(t, err)
@@ -81,7 +80,7 @@ func TestPauseStopPausedContainer(t *testing.T) {
err = client.ContainerStop(ctx, cID, nil)
require.NoError(t, err)
poll.WaitOn(t, containerIsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
}
func getEventActions(t *testing.T, messages <-chan events.Message, errs <-chan error) []string {
@@ -89,7 +88,7 @@ func getEventActions(t *testing.T, messages <-chan events.Message, errs <-chan e
for {
select {
case err := <-errs:
assert.Equal(t, err == nil || err == io.EOF, true)
assert.True(t, err == nil || err == io.EOF)
return actions
case e := <-messages:
actions = append(actions, e.Status)
@@ -5,9 +5,8 @@ import (
"testing"
"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/integration/internal/container"
"github.com/docker/docker/integration/internal/request"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -18,23 +17,9 @@ func TestPsFilter(t *testing.T) {
client := request.NewAPIClient(t)
ctx := context.Background()
createContainerForFilter := func(ctx context.Context, name string) string {
body, err := client.ContainerCreate(ctx,
&container.Config{
Cmd: []string{"top"},
Image: "busybox",
},
&container.HostConfig{},
&network.NetworkingConfig{},
name,
)
require.NoError(t, err)
return body.ID
}
prev := createContainerForFilter(ctx, "prev")
createContainerForFilter(ctx, "top")
next := createContainerForFilter(ctx, "next")
prev := container.Create(t, ctx, client, container.WithName("prev"))
container.Create(t, ctx, client, container.WithName("top"))
next := container.Create(t, ctx, client, container.WithName("next"))
containerIDs := func(containers []types.Container) []string {
entries := []string{}
@@ -0,0 +1,113 @@
package container // import "github.com/docker/docker/integration/container"
import (
"context"
"os"
"testing"
"time"
"github.com/docker/docker/api/types"
"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/fs"
"github.com/gotestyourself/gotestyourself/poll"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
if testEnv.OSType == "windows" {
return "c:", `\`
}
return "", "/"
}
// Test case for #5244: `docker rm` fails if bind dir doesn't exist anymore
func TestRemoveContainerWithRemovedVolume(t *testing.T) {
skip.If(t, testEnv.IsRemoteDaemon())
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
tempDir := fs.NewDir(t, "test-rm-container-with-removed-volume", fs.WithMode(0755))
defer tempDir.Remove()
cID := container.Run(t, ctx, client, container.WithCmd("true"), container.WithBind(tempDir.Path(), prefix+slash+"test"))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
err := os.RemoveAll(tempDir.Path())
require.NoError(t, err)
err = client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{
RemoveVolumes: true,
})
require.NoError(t, err)
_, _, err = client.ContainerInspectWithRaw(ctx, cID, true)
testutil.ErrorContains(t, err, "No such container")
}
// Test case for #2099/#2125
func TestRemoveContainerWithVolume(t *testing.T) {
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
cID := container.Run(t, ctx, client, container.WithCmd("true"), container.WithVolume(prefix+slash+"srv"))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
insp, _, err := client.ContainerInspectWithRaw(ctx, cID, true)
require.NoError(t, err)
assert.Equal(t, 1, len(insp.Mounts))
volName := insp.Mounts[0].Name
err = client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{
RemoveVolumes: true,
})
require.NoError(t, err)
volumes, err := client.VolumeList(ctx, filters.NewArgs(filters.Arg("name", volName)))
require.NoError(t, err)
assert.Equal(t, 0, len(volumes.Volumes))
}
func TestRemoveContainerRunning(t *testing.T) {
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
cID := container.Run(t, ctx, client)
err := client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{})
testutil.ErrorContains(t, err, "cannot remove a running container")
}
func TestRemoveContainerForceRemoveRunning(t *testing.T) {
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
cID := container.Run(t, ctx, client)
err := client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{
Force: true,
})
require.NoError(t, err)
}
func TestRemoveInvalidContainer(t *testing.T) {
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
err := client.ContainerRemove(ctx, "unknown", types.ContainerRemoveOptions{})
testutil.ErrorContains(t, err, "No such container")
}
@@ -51,11 +51,11 @@ func TestRenameStoppedContainer(t *testing.T) {
oldName := "first_name"
cID := container.Run(t, ctx, client, container.WithName(oldName), container.WithCmd("sh"))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.Name, "/"+oldName)
assert.Equal(t, "/"+oldName, inspect.Name)
newName := "new_name" + stringid.GenerateNonCryptoID()
err = client.ContainerRename(ctx, oldName, newName)
@@ -63,7 +63,7 @@ func TestRenameStoppedContainer(t *testing.T) {
inspect, err = client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.Name, "/"+newName)
assert.Equal(t, "/"+newName, inspect.Name)
}
func TestRenameRunningContainerAndReuse(t *testing.T) {
@@ -73,7 +73,7 @@ func TestRenameRunningContainerAndReuse(t *testing.T) {
oldName := "first_name"
cID := container.Run(t, ctx, client, container.WithName(oldName))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
newName := "new_name" + stringid.GenerateNonCryptoID()
err := client.ContainerRename(ctx, oldName, newName)
@@ -81,17 +81,17 @@ func TestRenameRunningContainerAndReuse(t *testing.T) {
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.Name, "/"+newName)
assert.Equal(t, "/"+newName, inspect.Name)
_, err = client.ContainerInspect(ctx, oldName)
testutil.ErrorContains(t, err, "No such container: "+oldName)
cID = container.Run(t, ctx, client, container.WithName(oldName))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
inspect, err = client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.Name, "/"+oldName)
assert.Equal(t, "/"+oldName, inspect.Name)
}
func TestRenameInvalidName(t *testing.T) {
@@ -101,14 +101,14 @@ func TestRenameInvalidName(t *testing.T) {
oldName := "first_name"
cID := container.Run(t, ctx, client, container.WithName(oldName))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerRename(ctx, oldName, "new:invalid")
testutil.ErrorContains(t, err, "Invalid container name")
inspect, err := client.ContainerInspect(ctx, oldName)
require.NoError(t, err)
assert.Equal(t, inspect.ID, cID)
assert.Equal(t, cID, inspect.ID)
}
// Test case for GitHub issue 22466
@@ -133,10 +133,14 @@ func TestRenameAnonymousContainer(t *testing.T) {
})
err = client.ContainerRename(ctx, cID, "container1")
require.NoError(t, err)
// Stop/Start the container to get registered
// FIXME(vdemeester) this is a really weird behavior as it fails otherwise
err = client.ContainerStop(ctx, "container1", nil)
require.NoError(t, err)
err = client.ContainerStart(ctx, "container1", types.ContainerStartOptions{})
require.NoError(t, err)
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
count := "-c"
if testEnv.OSType == "windows" {
@@ -148,11 +152,11 @@ func TestRenameAnonymousContainer(t *testing.T) {
}
c.HostConfig.NetworkMode = "network1"
}, container.WithCmd("ping", count, "1", "container1"))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
assert.Equal(t, inspect.State.ExitCode, 0)
assert.Equal(t, 0, inspect.State.ExitCode, "container %s exited with the wrong exitcode: %+v", cID, inspect)
}
// TODO: should be a unit test
@@ -162,7 +166,7 @@ func TestRenameContainerWithSameName(t *testing.T) {
client := request.NewAPIClient(t)
cID := container.Run(t, ctx, client, container.WithName("old"))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerRename(ctx, "old", "old")
testutil.ErrorContains(t, err, "Renaming a container with the same name")
err = client.ContainerRename(ctx, cID, "old")
@@ -175,22 +179,22 @@ func TestRenameContainerWithSameName(t *testing.T) {
// of the linked container should be updated so that the other
// container could still reference to the container that is renamed.
func TestRenameContainerWithLinkedContainer(t *testing.T) {
skip.If(t, !testEnv.IsLocalDaemon())
skip.If(t, testEnv.IsRemoteDaemon())
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
db1ID := container.Run(t, ctx, client, container.WithName("db1"))
poll.WaitOn(t, containerIsInState(ctx, client, db1ID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, db1ID, "running"), poll.WithDelay(100*time.Millisecond))
app1ID := container.Run(t, ctx, client, container.WithName("app1"), container.WithLinks("db1:/mysql"))
poll.WaitOn(t, containerIsInState(ctx, client, app1ID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, app1ID, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerRename(ctx, "app1", "app2")
require.NoError(t, err)
inspect, err := client.ContainerInspect(ctx, "app2/mysql")
require.NoError(t, err)
assert.Equal(t, inspect.ID, db1ID)
assert.Equal(t, db1ID, inspect.ID)
}
@@ -23,7 +23,7 @@ func TestResize(t *testing.T) {
cID := container.Run(t, ctx, client)
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerResize(ctx, cID, types.ResizeOptions{
Height: 40,
@@ -39,12 +39,12 @@ func TestResizeWithInvalidSize(t *testing.T) {
cID := container.Run(t, ctx, client)
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
endpoint := "/containers/" + cID + "/resize?h=foo&w=bar"
res, _, err := req.Post(endpoint)
require.NoError(t, err)
assert.Equal(t, res.StatusCode, http.StatusBadRequest)
assert.Equal(t, http.StatusBadRequest, res.StatusCode)
}
func TestResizeWhenContainerNotStarted(t *testing.T) {
@@ -54,7 +54,7 @@ func TestResizeWhenContainerNotStarted(t *testing.T) {
cID := container.Run(t, ctx, client, container.WithCmd("echo"))
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
err := client.ContainerResize(ctx, cID, types.ResizeOptions{
Height: 40,
@@ -9,9 +9,11 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/integration-cli/daemon"
"github.com/gotestyourself/gotestyourself/skip"
)
func TestDaemonRestartKillContainers(t *testing.T) {
skip.If(t, testEnv.IsRemoteDaemon(), "cannot start daemon on remote test run")
type testCase struct {
desc string
config *container.Config
@@ -28,7 +28,7 @@ func TestStats(t *testing.T) {
cID := container.Run(t, ctx, client)
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
resp, err := client.ContainerStats(ctx, cID, false)
require.NoError(t, err)
@@ -8,7 +8,6 @@ import (
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/request"
"github.com/gotestyourself/gotestyourself/icmd"
@@ -30,7 +29,7 @@ func TestStopContainerWithRestartPolicyAlways(t *testing.T) {
}
for _, name := range names {
poll.WaitOn(t, containerIsInState(ctx, client, name, "running", "restarting"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, name, "running", "restarting"), poll.WithDelay(100*time.Millisecond))
}
for _, name := range names {
@@ -39,7 +38,7 @@ func TestStopContainerWithRestartPolicyAlways(t *testing.T) {
}
for _, name := range names {
poll.WaitOn(t, containerIsStopped(ctx, client, name), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsStopped(ctx, client, name), poll.WithDelay(100*time.Millisecond))
}
}
@@ -52,7 +51,7 @@ func TestDeleteDevicemapper(t *testing.T) {
id := container.Run(t, ctx, client, container.WithName("foo"), container.WithCmd("echo"))
poll.WaitOn(t, containerIsStopped(ctx, client, id), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsStopped(ctx, client, id), poll.WithDelay(100*time.Millisecond))
inspect, err := client.ContainerInspect(ctx, id)
require.NoError(t, err)
@@ -70,33 +69,3 @@ func TestDeleteDevicemapper(t *testing.T) {
err = client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{})
require.NoError(t, err)
}
func containerIsStopped(ctx context.Context, client client.APIClient, containerID string) func(log poll.LogT) poll.Result {
return func(log poll.LogT) poll.Result {
inspect, err := client.ContainerInspect(ctx, containerID)
switch {
case err != nil:
return poll.Error(err)
case !inspect.State.Running:
return poll.Success()
default:
return poll.Continue("waiting for container to be stopped")
}
}
}
func containerIsInState(ctx context.Context, client client.APIClient, containerID string, state ...string) func(log poll.LogT) poll.Result {
return func(log poll.LogT) poll.Result {
inspect, err := client.ContainerInspect(ctx, containerID)
if err != nil {
return poll.Error(err)
}
for _, v := range state {
if inspect.State.Status == v {
return poll.Success()
}
}
return poll.Continue("waiting for container to be running, currently %s", inspect.State.Status)
}
}
@@ -31,7 +31,7 @@ func TestUpdateMemory(t *testing.T) {
}
})
poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
const (
setMemory int64 = 314572800
@@ -39,7 +39,7 @@ func TestUpdateRestartPolicy(t *testing.T) {
timeout = 180 * time.Second
}
poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(timeout))
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(timeout))
inspect, err := client.ContainerInspect(ctx, cID)
require.NoError(t, err)
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/request"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -16,10 +16,9 @@ func TestCommitInheritsEnv(t *testing.T) {
client := request.NewAPIClient(t)
ctx := context.Background()
createResp1, err := client.ContainerCreate(ctx, &container.Config{Image: "busybox"}, nil, nil, "")
require.NoError(t, err)
cID1 := container.Create(t, ctx, client)
commitResp1, err := client.ContainerCommit(ctx, createResp1.ID, types.ContainerCommitOptions{
commitResp1, err := client.ContainerCommit(ctx, cID1, types.ContainerCommitOptions{
Changes: []string{"ENV PATH=/bin"},
Reference: "test-commit-image",
})
@@ -31,10 +30,9 @@ func TestCommitInheritsEnv(t *testing.T) {
expectedEnv1 := []string{"PATH=/bin"}
assert.Equal(t, expectedEnv1, image1.Config.Env)
createResp2, err := client.ContainerCreate(ctx, &container.Config{Image: image1.ID}, nil, nil, "")
require.NoError(t, err)
cID2 := container.Create(t, ctx, client, container.WithImage(image1.ID))
commitResp2, err := client.ContainerCommit(ctx, createResp2.ID, types.ContainerCommitOptions{
commitResp2, err := client.ContainerCommit(ctx, cID2, types.ContainerCommitOptions{
Changes: []string{"ENV PATH=/usr/bin:$PATH"},
Reference: "test-commit-image",
})
@@ -0,0 +1,60 @@
package image // import "github.com/docker/docker/integration/image"
import (
"context"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/request"
"github.com/docker/docker/internal/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRemoveImageOrphaning(t *testing.T) {
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
img := "test-container-orphaning"
// Create a container from busybox, and commit a small change so we have a new image
cID1 := container.Create(t, ctx, client, container.WithCmd(""))
commitResp1, err := client.ContainerCommit(ctx, cID1, types.ContainerCommitOptions{
Changes: []string{`ENTRYPOINT ["true"]`},
Reference: img,
})
require.NoError(t, err)
// verifies that reference now points to first image
resp, _, err := client.ImageInspectWithRaw(ctx, img)
require.NoError(t, err)
assert.Equal(t, resp.ID, commitResp1.ID)
// Create a container from created image, and commit a small change with same reference name
cID2 := container.Create(t, ctx, client, container.WithImage(img), container.WithCmd(""))
commitResp2, err := client.ContainerCommit(ctx, cID2, types.ContainerCommitOptions{
Changes: []string{`LABEL Maintainer="Integration Tests"`},
Reference: img,
})
require.NoError(t, err)
// verifies that reference now points to second image
resp, _, err = client.ImageInspectWithRaw(ctx, img)
require.NoError(t, err)
assert.Equal(t, resp.ID, commitResp2.ID)
// try to remove the image, should not error out.
_, err = client.ImageRemove(ctx, img, types.ImageRemoveOptions{})
require.NoError(t, err)
// check if the first image is still there
resp, _, err = client.ImageInspectWithRaw(ctx, commitResp1.ID)
require.NoError(t, err)
assert.Equal(t, resp.ID, commitResp1.ID)
// check if the second image has been deleted
_, _, err = client.ImageInspectWithRaw(ctx, commitResp2.ID)
testutil.ErrorContains(t, err, "No such image:")
}
@@ -1,6 +1,8 @@
package container
import (
"fmt"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/strslice"
"github.com/docker/go-connections/nat"
@@ -20,6 +22,13 @@ func WithLinks(links ...string) func(*TestContainerConfig) {
}
}
// WithImage sets the image of the container
func WithImage(image string) func(*TestContainerConfig) {
return func(c *TestContainerConfig) {
c.Config.Image = image
}
}
// WithCmd sets the comannds of the container
func WithCmd(cmds ...string) func(*TestContainerConfig) {
return func(c *TestContainerConfig) {
@@ -57,3 +66,20 @@ func WithWorkingDir(dir string) func(*TestContainerConfig) {
c.Config.WorkingDir = dir
}
}
// WithVolume sets the volume of the container
func WithVolume(name string) func(*TestContainerConfig) {
return func(c *TestContainerConfig) {
if c.Config.Volumes == nil {
c.Config.Volumes = map[string]struct{}{}
}
c.Config.Volumes[name] = struct{}{}
}
}
// WithBind sets the bind mount of the container
func WithBind(src, target string) func(*TestContainerConfig) {
return func(c *TestContainerConfig) {
c.HostConfig.Binds = append(c.HostConfig.Binds, fmt.Sprintf("%s:%s", src, target))
}
}
@@ -0,0 +1,41 @@
package container
import (
"strings"
"github.com/docker/docker/client"
"github.com/gotestyourself/gotestyourself/poll"
"golang.org/x/net/context"
)
// IsStopped verifies the container is in stopped state.
func IsStopped(ctx context.Context, client client.APIClient, containerID string) func(log poll.LogT) poll.Result {
return func(log poll.LogT) poll.Result {
inspect, err := client.ContainerInspect(ctx, containerID)
switch {
case err != nil:
return poll.Error(err)
case !inspect.State.Running:
return poll.Success()
default:
return poll.Continue("waiting for container to be stopped")
}
}
}
// IsInState verifies the container is in one of the specified state, e.g., "running", "exited", etc.
func IsInState(ctx context.Context, client client.APIClient, containerID string, state ...string) func(log poll.LogT) poll.Result {
return func(log poll.LogT) poll.Result {
inspect, err := client.ContainerInspect(ctx, containerID)
if err != nil {
return poll.Error(err)
}
for _, v := range state {
if inspect.State.Status == v {
return poll.Success()
}
}
return poll.Continue("waiting for container to be one of (%s), currently %s", strings.Join(state, ", "), inspect.State.Status)
}
}
@@ -20,8 +20,8 @@ func NewAPIClient(t *testing.T, ops ...func(*client.Client) error) client.APICli
return clt
}
// 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 {
// 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()
}
@@ -37,6 +37,6 @@ func daemonTime(ctx context.Context, t *testing.T, client client.APIClient, test
// 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)
dt := DaemonTime(ctx, t, client, testEnv)
return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
}
@@ -129,32 +129,7 @@ func createSecret(ctx context.Context, t *testing.T, client client.APIClient, na
return secret.ID
}
func TestSecretsCreate(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
defer setupTest(t)()
d := swarm.NewSwarm(t, testEnv)
defer d.Stop(t)
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
require.NoError(t, err)
ctx := context.Background()
testName := "test_secret"
createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
require.NoError(t, err)
// create an already existin secret, daemon should return a status code of 409
_, err = client.SecretCreate(ctx, swarmtypes.SecretSpec{
Annotations: swarmtypes.Annotations{
Name: testName,
},
Data: []byte("TESTINGDATA"),
})
testutil.ErrorContains(t, err, "already exists")
}
func TestSecretsDelete(t *testing.T) {
func TestSecretsCreateAndDelete(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
defer setupTest(t)()
@@ -167,12 +142,17 @@ func TestSecretsDelete(t *testing.T) {
testName := "test_secret"
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
require.NoError(t, err)
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
require.NoError(t, err)
assert.Equal(t, insp.ID, secretID)
// create an already existin secret, daemon should return a status code of 409
_, err = client.SecretCreate(ctx, swarmtypes.SecretSpec{
Annotations: swarmtypes.Annotations{
Name: testName,
},
Data: []byte("TESTINGDATA"),
})
testutil.ErrorContains(t, err, "already exists")
// Ported from original TestSecretsDelete
err = client.SecretRemove(ctx, secretID)
require.NoError(t, err)
@@ -181,6 +161,20 @@ func TestSecretsDelete(t *testing.T) {
err = client.SecretRemove(ctx, "non-existin")
testutil.ErrorContains(t, err, "No such secret: non-existin")
// Ported from original TestSecretsCreteaWithLabels
testName = "test_secret_with_labels"
secretID = createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), map[string]string{
"key1": "value1",
"key2": "value2",
})
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
require.NoError(t, err)
assert.Equal(t, insp.Spec.Name, testName)
assert.Equal(t, len(insp.Spec.Labels), 2)
assert.Equal(t, insp.Spec.Labels["key1"], "value1")
assert.Equal(t, insp.Spec.Labels["key2"], "value2")
}
func TestSecretsUpdate(t *testing.T) {
@@ -18,7 +18,7 @@ import (
)
func TestInspect(t *testing.T) {
skip.IfCondition(t, !testEnv.IsLocalDaemon())
skip.IfCondition(t, testEnv.IsRemoteDaemon())
defer setupTest(t)()
d := swarm.NewSwarm(t, testEnv)
defer d.Stop(t)
@@ -2,15 +2,22 @@ package system // import "github.com/docker/docker/integration/system"
import (
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"strconv"
"testing"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/strslice"
req "github.com/docker/docker/integration-cli/request"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/request"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -58,3 +65,55 @@ func TestEvents(t *testing.T) {
}
}
// Test case for #18888: Events messages have been switched from generic
// `JSONMessage` to `events.Message` types. The switch does not break the
// backward compatibility so old `JSONMessage` could still be used.
// This test verifies that backward compatibility maintains.
func TestEventsBackwardsCompatible(t *testing.T) {
defer setupTest(t)()
ctx := context.Background()
client := request.NewAPIClient(t)
since := request.DaemonTime(ctx, t, client, testEnv)
ts := strconv.FormatInt(since.Unix(), 10)
cID := container.Create(t, ctx, client)
// In case there is no events, the API should have responded immediately (not blocking),
// The test here makes sure the response time is less than 3 sec.
expectedTime := time.Now().Add(3 * time.Second)
emptyResp, emptyBody, err := req.Get("/events")
require.NoError(t, err)
defer emptyBody.Close()
assert.Equal(t, http.StatusOK, emptyResp.StatusCode)
assert.True(t, time.Now().Before(expectedTime), "timeout waiting for events api to respond, should have responded immediately")
// We also test to make sure the `events.Message` is compatible with `JSONMessage`
q := url.Values{}
q.Set("since", ts)
_, body, err := req.Get("/events?" + q.Encode())
require.NoError(t, err)
defer body.Close()
dec := json.NewDecoder(body)
var containerCreateEvent *jsonmessage.JSONMessage
for {
var event jsonmessage.JSONMessage
if err := dec.Decode(&event); err != nil {
if err == io.EOF {
break
}
t.Fatal(err)
}
if event.Status == "create" && event.ID == cID {
containerCreateEvent = &event
break
}
}
assert.NotNil(t, containerCreateEvent)
assert.Equal(t, "create", containerCreateEvent.Status)
assert.Equal(t, cID, containerCreateEvent.ID)
assert.Equal(t, "busybox", containerCreateEvent.From)
}
@@ -0,0 +1,33 @@
package volume // import "github.com/docker/docker/integration/volume"
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,113 @@
package volume
import (
"context"
"fmt"
"strings"
"testing"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
volumetypes "github.com/docker/docker/api/types/volume"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/request"
"github.com/docker/docker/internal/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestVolumesCreateAndList(t *testing.T) {
defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()
name := t.Name()
vol, err := client.VolumeCreate(ctx, volumetypes.VolumesCreateBody{
Name: name,
})
require.NoError(t, err)
expected := types.Volume{
// Ignore timestamp of CreatedAt
CreatedAt: vol.CreatedAt,
Driver: "local",
Scope: "local",
Name: name,
Mountpoint: fmt.Sprintf("%s/volumes/%s/_data", testEnv.DaemonInfo.DockerRootDir, name),
}
assert.Equal(t, vol, expected)
volumes, err := client.VolumeList(ctx, filters.Args{})
require.NoError(t, err)
assert.Equal(t, len(volumes.Volumes), 1)
assert.NotNil(t, volumes.Volumes[0])
assert.Equal(t, *volumes.Volumes[0], expected)
}
func TestVolumesRemove(t *testing.T) {
defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
id := container.Create(t, ctx, client, container.WithVolume(prefix+"foo"))
c, err := client.ContainerInspect(ctx, id)
require.NoError(t, err)
vname := c.Mounts[0].Name
err = client.VolumeRemove(ctx, vname, false)
testutil.ErrorContains(t, err, "volume is in use")
err = client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{
Force: true,
})
require.NoError(t, err)
err = client.VolumeRemove(ctx, vname, false)
require.NoError(t, err)
}
func TestVolumesInspect(t *testing.T) {
defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()
// sampling current time minus a minute so to now have false positive in case of delays
now := time.Now().Truncate(time.Minute)
name := t.Name()
_, err := client.VolumeCreate(ctx, volumetypes.VolumesCreateBody{
Name: name,
})
require.NoError(t, err)
vol, err := client.VolumeInspect(ctx, name)
require.NoError(t, err)
expected := types.Volume{
// Ignore timestamp of CreatedAt
CreatedAt: vol.CreatedAt,
Driver: "local",
Scope: "local",
Name: name,
Mountpoint: fmt.Sprintf("%s/volumes/%s/_data", testEnv.DaemonInfo.DockerRootDir, name),
}
assert.Equal(t, vol, expected)
// comparing CreatedAt field time for the new volume to now. Removing a minute from both to avoid false positive
testCreatedAt, err := time.Parse(time.RFC3339, strings.TrimSpace(vol.CreatedAt))
require.NoError(t, err)
testCreatedAt = testCreatedAt.Truncate(time.Minute)
assert.Equal(t, testCreatedAt.Equal(now), true, "Time Volume is CreatedAt not equal to current time")
}
func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
if testEnv.OSType == "windows" {
return "c:", `\`
}
return "", "/"
}
@@ -96,7 +96,7 @@ func toSlash(path string) string {
}
// IsLocalDaemon is true if the daemon under test is on the same
// host as the CLI.
// 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
@@ -115,6 +115,12 @@ 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()
}
// Print the execution details to stdout
// TODO: print everything
func (e *Execution) Print() {
@@ -2,6 +2,7 @@ package plugins // import "github.com/docker/docker/pkg/plugins"
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
@@ -13,7 +14,9 @@ import (
"github.com/docker/docker/pkg/plugins/transport"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
@@ -232,3 +235,43 @@ func TestClientSendFile(t *testing.T) {
}
assert.Equal(t, m, output)
}
func TestClientWithRequestTimeout(t *testing.T) {
timeout := 1 * time.Millisecond
testHandler := func(w http.ResponseWriter, r *http.Request) {
time.Sleep(timeout + 1*time.Millisecond)
w.WriteHeader(http.StatusOK)
}
srv := httptest.NewServer(http.HandlerFunc(testHandler))
defer srv.Close()
client := &Client{http: srv.Client(), requestFactory: &testRequestWrapper{srv}}
_, err := client.callWithRetry("/Plugin.Hello", nil, false, WithRequestTimeout(timeout))
require.Error(t, err, "expected error")
err = errors.Cause(err)
switch e := err.(type) {
case *url.Error:
err = e.Err
}
require.Equal(t, context.DeadlineExceeded, err)
}
type testRequestWrapper struct {
*httptest.Server
}
func (w *testRequestWrapper) NewRequest(path string, data io.Reader) (*http.Request, error) {
req, err := http.NewRequest("POST", path, data)
if err != nil {
return nil, err
}
u, err := url.Parse(w.Server.URL)
if err != nil {
return nil, err
}
req.URL = u
return req, nil
}
+9 -2
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/boltdb/bolt"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -28,7 +29,10 @@ func setMeta(tx *bolt.Tx, name string, meta volumeMetadata) error {
if err != nil {
return err
}
b := tx.Bucket(volumeBucketName)
b, err := tx.CreateBucketIfNotExists(volumeBucketName)
if err != nil {
return errors.Wrap(err, "error creating volume bucket")
}
return errors.Wrap(b.Put([]byte(name), metaJSON), "error setting volume metadata")
}
@@ -42,8 +46,11 @@ func (s *VolumeStore) getMeta(name string) (volumeMetadata, error) {
func getMeta(tx *bolt.Tx, name string, meta *volumeMetadata) error {
b := tx.Bucket(volumeBucketName)
if b == nil {
return errdefs.NotFound(errors.New("volume bucket does not exist"))
}
val := b.Get([]byte(name))
if string(val) == "" {
if len(val) == 0 {
return nil
}
if err := json.Unmarshal(val, meta); err != nil {
+51
View File
@@ -0,0 +1,51 @@
package store
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"
"github.com/boltdb/bolt"
"github.com/stretchr/testify/require"
)
func TestSetGetMeta(t *testing.T) {
t.Parallel()
dir, err := ioutil.TempDir("", "test-set-get")
require.NoError(t, err)
defer os.RemoveAll(dir)
db, err := bolt.Open(filepath.Join(dir, "db"), 0600, &bolt.Options{Timeout: 1 * time.Second})
require.NoError(t, err)
store := &VolumeStore{db: db}
_, err = store.getMeta("test")
require.Error(t, err)
err = db.Update(func(tx *bolt.Tx) error {
_, err := tx.CreateBucket(volumeBucketName)
return err
})
require.NoError(t, err)
meta, err := store.getMeta("test")
require.NoError(t, err)
require.Equal(t, volumeMetadata{}, meta)
testMeta := volumeMetadata{
Name: "test",
Driver: "fake",
Labels: map[string]string{"a": "1", "b": "2"},
Options: map[string]string{"foo": "bar"},
}
err = store.setMeta("test", testMeta)
require.NoError(t, err)
meta, err = store.getMeta("test")
require.NoError(t, err)
require.Equal(t, testMeta, meta)
}
@@ -0,0 +1,55 @@
package store
import (
"io/ioutil"
"os"
"testing"
"github.com/docker/docker/volume"
volumedrivers "github.com/docker/docker/volume/drivers"
volumetestutils "github.com/docker/docker/volume/testutils"
"github.com/stretchr/testify/require"
)
func TestRestore(t *testing.T) {
t.Parallel()
dir, err := ioutil.TempDir("", "test-restore")
require.NoError(t, err)
defer os.RemoveAll(dir)
driverName := "test-restore"
volumedrivers.Register(volumetestutils.NewFakeDriver(driverName), driverName)
defer volumedrivers.Unregister("test-restore")
s, err := New(dir)
require.NoError(t, err)
defer s.Shutdown()
_, err = s.Create("test1", driverName, nil, nil)
require.NoError(t, err)
testLabels := map[string]string{"a": "1"}
testOpts := map[string]string{"foo": "bar"}
_, err = s.Create("test2", driverName, testOpts, testLabels)
require.NoError(t, err)
s.Shutdown()
s, err = New(dir)
require.NoError(t, err)
v, err := s.Get("test1")
require.NoError(t, err)
dv := v.(volume.DetailedVolume)
var nilMap map[string]string
require.Equal(t, nilMap, dv.Options())
require.Equal(t, nilMap, dv.Labels())
v, err = s.Get("test2")
require.NoError(t, err)
dv = v.(volume.DetailedVolume)
require.Equal(t, testOpts, dv.Options())
require.Equal(t, testLabels, dv.Labels())
}
+13 -2
View File
@@ -29,7 +29,10 @@ type volumeWrapper struct {
}
func (v volumeWrapper) Options() map[string]string {
options := map[string]string{}
if v.options == nil {
return nil
}
options := make(map[string]string, len(v.options))
for key, value := range v.options {
options[key] = value
}
@@ -37,7 +40,15 @@ func (v volumeWrapper) Options() map[string]string {
}
func (v volumeWrapper) Labels() map[string]string {
return v.labels
if v.labels == nil {
return nil
}
labels := make(map[string]string, len(v.labels))
for key, value := range v.labels {
labels[key] = value
}
return labels
}
func (v volumeWrapper) Scope() string {
@@ -12,6 +12,8 @@ import (
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
volumetestutils "github.com/docker/docker/volume/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCreate(t *testing.T) {
@@ -291,6 +293,7 @@ func TestDefererencePluginOnCreateError(t *testing.T) {
pg := volumetestutils.NewFakePluginGetter(p)
volumedrivers.RegisterPluginGetter(pg)
defer volumedrivers.RegisterPluginGetter(nil)
dir, err := ioutil.TempDir("", "test-plugin-deref-err")
if err != nil {
@@ -320,3 +323,103 @@ func TestDefererencePluginOnCreateError(t *testing.T) {
t.Fatalf("expected 1 plugin reference, got: %d", refs)
}
}
func TestRefDerefRemove(t *testing.T) {
t.Parallel()
driverName := "test-ref-deref-remove"
s, cleanup := setupTest(t, driverName)
defer cleanup(t)
v, err := s.CreateWithRef("test", driverName, "test-ref", nil, nil)
require.NoError(t, err)
err = s.Remove(v)
require.Error(t, err)
require.Equal(t, errVolumeInUse, err.(*OpErr).Err)
s.Dereference(v, "test-ref")
err = s.Remove(v)
require.NoError(t, err)
}
func TestGet(t *testing.T) {
t.Parallel()
driverName := "test-get"
s, cleanup := setupTest(t, driverName)
defer cleanup(t)
_, err := s.Get("not-exist")
require.Error(t, err)
require.Equal(t, errNoSuchVolume, err.(*OpErr).Err)
v1, err := s.Create("test", driverName, nil, map[string]string{"a": "1"})
require.NoError(t, err)
v2, err := s.Get("test")
require.NoError(t, err)
require.Equal(t, v1, v2)
dv := v2.(volume.DetailedVolume)
require.Equal(t, "1", dv.Labels()["a"])
err = s.Remove(v1)
require.NoError(t, err)
}
func TestGetWithRef(t *testing.T) {
t.Parallel()
driverName := "test-get-with-ref"
s, cleanup := setupTest(t, driverName)
defer cleanup(t)
_, err := s.GetWithRef("not-exist", driverName, "test-ref")
require.Error(t, err)
v1, err := s.Create("test", driverName, nil, map[string]string{"a": "1"})
require.NoError(t, err)
v2, err := s.GetWithRef("test", driverName, "test-ref")
require.NoError(t, err)
require.Equal(t, v1, v2)
err = s.Remove(v2)
require.Error(t, err)
require.Equal(t, errVolumeInUse, err.(*OpErr).Err)
s.Dereference(v2, "test-ref")
err = s.Remove(v2)
require.NoError(t, err)
}
func setupTest(t *testing.T, name string) (*VolumeStore, func(*testing.T)) {
t.Helper()
s, cleanup := newTestStore(t)
volumedrivers.Register(volumetestutils.NewFakeDriver(name), name)
return s, func(t *testing.T) {
cleanup(t)
volumedrivers.Unregister(name)
}
}
func newTestStore(t *testing.T) (*VolumeStore, func(*testing.T)) {
t.Helper()
dir, err := ioutil.TempDir("", "store-root")
require.NoError(t, err)
cleanup := func(t *testing.T) {
err := os.RemoveAll(dir)
assert.NoError(t, err)
}
s, err := New(dir)
assert.NoError(t, err)
return s, func(t *testing.T) {
s.Shutdown()
cleanup(t)
}
}