Merge pull request #40477 from cpuguy83/19.03_40446_check_other_mounts
[19.03] Check tmpfs mounts before create anon volume
This commit is contained in:
commit
ad2c5440b5
3 changed files with 69 additions and 3 deletions
|
@ -46,7 +46,9 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
|
|||
|
||||
// Skip volumes for which we already have something mounted on that
|
||||
// destination because of a --volume-from.
|
||||
if container.IsDestinationMounted(destination) {
|
||||
if container.HasMountFor(destination) {
|
||||
logrus.WithField("container", container.ID).WithField("destination", spec).Debug("mountpoint already exists, skipping anonymous volume")
|
||||
// Not an error, this could easily have come from the image config.
|
||||
continue
|
||||
}
|
||||
path, err := container.GetResourcePath(destination)
|
||||
|
|
|
@ -535,3 +535,50 @@ func TestCreateWithInvalidHealthcheckParams(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that anonymous volumes can be overritten by tmpfs
|
||||
// https://github.com/moby/moby/issues/40446
|
||||
func TestCreateTmpfsOverrideAnonymousVolume(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows", "windows does not support tmpfs")
|
||||
defer setupTest(t)()
|
||||
client := testEnv.APIClient()
|
||||
ctx := context.Background()
|
||||
|
||||
id := ctr.Create(ctx, t, client,
|
||||
ctr.WithVolume("/foo"),
|
||||
ctr.WithTmpfs("/foo"),
|
||||
ctr.WithVolume("/bar"),
|
||||
ctr.WithTmpfs("/bar:size=999"),
|
||||
ctr.WithCmd("/bin/sh", "-c", "mount | grep '/foo' | grep tmpfs && mount | grep '/bar' | grep tmpfs"),
|
||||
)
|
||||
|
||||
defer func() {
|
||||
err := client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{Force: true})
|
||||
assert.NilError(t, err)
|
||||
}()
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, id)
|
||||
assert.NilError(t, err)
|
||||
// tmpfs do not currently get added to inspect.Mounts
|
||||
// Normally an anoynmous volume would, except now tmpfs should prevent that.
|
||||
assert.Assert(t, is.Len(inspect.Mounts, 0))
|
||||
|
||||
chWait, chErr := client.ContainerWait(ctx, id, container.WaitConditionNextExit)
|
||||
assert.NilError(t, client.ContainerStart(ctx, id, types.ContainerStartOptions{}))
|
||||
|
||||
timeout := time.NewTimer(30 * time.Second)
|
||||
defer timeout.Stop()
|
||||
|
||||
select {
|
||||
case <-timeout.C:
|
||||
t.Fatal("timeout waiting for container to exit")
|
||||
case status := <-chWait:
|
||||
var errMsg string
|
||||
if status.Error != nil {
|
||||
errMsg = status.Error.Message
|
||||
}
|
||||
assert.Equal(t, int(status.StatusCode), 0, errMsg)
|
||||
case err := <-chErr:
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package container
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
mounttypes "github.com/docker/docker/api/types/mount"
|
||||
|
@ -77,12 +78,12 @@ func WithMount(m mounttypes.Mount) func(*TestContainerConfig) {
|
|||
}
|
||||
|
||||
// WithVolume sets the volume of the container
|
||||
func WithVolume(name string) func(*TestContainerConfig) {
|
||||
func WithVolume(target string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
if c.Config.Volumes == nil {
|
||||
c.Config.Volumes = map[string]struct{}{}
|
||||
}
|
||||
c.Config.Volumes[name] = struct{}{}
|
||||
c.Config.Volumes[target] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +94,22 @@ func WithBind(src, target string) func(*TestContainerConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
// WithTmpfs sets a target path in the container to a tmpfs
|
||||
func WithTmpfs(target string) func(config *TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
if c.HostConfig.Tmpfs == nil {
|
||||
c.HostConfig.Tmpfs = make(map[string]string)
|
||||
}
|
||||
|
||||
spec := strings.SplitN(target, ":", 2)
|
||||
var opts string
|
||||
if len(spec) > 1 {
|
||||
opts = spec[1]
|
||||
}
|
||||
c.HostConfig.Tmpfs[spec[0]] = opts
|
||||
}
|
||||
}
|
||||
|
||||
// WithIPv4 sets the specified ip for the specified network of the container
|
||||
func WithIPv4(network, ip string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
|
|
Loading…
Reference in a new issue