mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
oci: add integration tests for kernel.domainname configuration
This also includes a few refactors of oci_linux_test.go. Signed-off-by: Aleksa Sarai <asarai@suse.de>
This commit is contained in:
parent
7417f50575
commit
f38ac72bca
2 changed files with 123 additions and 34 deletions
|
@ -1,29 +1,67 @@
|
||||||
package daemon // import "github.com/docker/docker/daemon"
|
package daemon // import "github.com/docker/docker/daemon"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/daemon/config"
|
"github.com/docker/docker/daemon/config"
|
||||||
"github.com/docker/docker/oci"
|
"github.com/docker/docker/daemon/network"
|
||||||
|
"github.com/docker/docker/pkg/containerfs"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"github.com/docker/libnetwork"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func setupFakeDaemon(t *testing.T, c *container.Container) *Daemon {
|
||||||
|
root, err := ioutil.TempDir("", "oci_linux_test-root")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
rootfs := filepath.Join(root, "rootfs")
|
||||||
|
err = os.MkdirAll(rootfs, 0755)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
netController, err := libnetwork.New()
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
d := &Daemon{
|
||||||
|
// some empty structs to avoid getting a panic
|
||||||
|
// caused by a null pointer dereference
|
||||||
|
idMapping: &idtools.IdentityMapping{},
|
||||||
|
configStore: &config.Config{},
|
||||||
|
linkIndex: newLinkIndex(),
|
||||||
|
netController: netController,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Root = root
|
||||||
|
c.BaseFS = containerfs.NewLocalContainerFS(rootfs)
|
||||||
|
|
||||||
|
if c.Config == nil {
|
||||||
|
c.Config = new(containertypes.Config)
|
||||||
|
}
|
||||||
|
if c.HostConfig == nil {
|
||||||
|
c.HostConfig = new(containertypes.HostConfig)
|
||||||
|
}
|
||||||
|
if c.NetworkSettings == nil {
|
||||||
|
c.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanupFakeContainer(c *container.Container) {
|
||||||
|
os.RemoveAll(c.Root)
|
||||||
|
}
|
||||||
|
|
||||||
// TestTmpfsDevShmNoDupMount checks that a user-specified /dev/shm tmpfs
|
// TestTmpfsDevShmNoDupMount checks that a user-specified /dev/shm tmpfs
|
||||||
// mount (as in "docker run --tmpfs /dev/shm:rw,size=NNN") does not result
|
// mount (as in "docker run --tmpfs /dev/shm:rw,size=NNN") does not result
|
||||||
// in "Duplicate mount point" error from the engine.
|
// in "Duplicate mount point" error from the engine.
|
||||||
// https://github.com/moby/moby/issues/35455
|
// https://github.com/moby/moby/issues/35455
|
||||||
func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
||||||
d := Daemon{
|
|
||||||
// some empty structs to avoid getting a panic
|
|
||||||
// caused by a null pointer dereference
|
|
||||||
idMapping: &idtools.IdentityMapping{},
|
|
||||||
configStore: &config.Config{},
|
|
||||||
}
|
|
||||||
c := &container.Container{
|
c := &container.Container{
|
||||||
ShmPath: "foobar", // non-empty, for c.IpcMounts() to work
|
ShmPath: "foobar", // non-empty, for c.IpcMounts() to work
|
||||||
HostConfig: &containertypes.HostConfig{
|
HostConfig: &containertypes.HostConfig{
|
||||||
|
@ -34,19 +72,10 @@ func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
d := setupFakeDaemon(t, c)
|
||||||
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
// Mimic the code flow of daemon.createSpec(), enough to reproduce the issue
|
_, err := d.createSpec(c)
|
||||||
ms, err := d.setupMounts(c)
|
|
||||||
assert.Check(t, err)
|
|
||||||
|
|
||||||
ms = append(ms, c.IpcMounts()...)
|
|
||||||
|
|
||||||
tmpfsMounts, err := c.TmpfsMounts()
|
|
||||||
assert.Check(t, err)
|
|
||||||
ms = append(ms, tmpfsMounts...)
|
|
||||||
|
|
||||||
s := oci.DefaultSpec()
|
|
||||||
err = setMounts(&d, &s, c, ms)
|
|
||||||
assert.Check(t, err)
|
assert.Check(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,28 +84,16 @@ func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
||||||
// the resulting /dev/shm mount is NOT made read-only.
|
// the resulting /dev/shm mount is NOT made read-only.
|
||||||
// https://github.com/moby/moby/issues/36503
|
// https://github.com/moby/moby/issues/36503
|
||||||
func TestIpcPrivateVsReadonly(t *testing.T) {
|
func TestIpcPrivateVsReadonly(t *testing.T) {
|
||||||
d := Daemon{
|
|
||||||
// some empty structs to avoid getting a panic
|
|
||||||
// caused by a null pointer dereference
|
|
||||||
idMapping: &idtools.IdentityMapping{},
|
|
||||||
configStore: &config.Config{},
|
|
||||||
}
|
|
||||||
c := &container.Container{
|
c := &container.Container{
|
||||||
HostConfig: &containertypes.HostConfig{
|
HostConfig: &containertypes.HostConfig{
|
||||||
IpcMode: containertypes.IpcMode("private"),
|
IpcMode: containertypes.IpcMode("private"),
|
||||||
ReadonlyRootfs: true,
|
ReadonlyRootfs: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
d := setupFakeDaemon(t, c)
|
||||||
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
// We can't call createSpec() so mimick the minimal part
|
s, err := d.createSpec(c)
|
||||||
// of its code flow, just enough to reproduce the issue.
|
|
||||||
ms, err := d.setupMounts(c)
|
|
||||||
assert.Check(t, err)
|
|
||||||
|
|
||||||
s := oci.DefaultSpec()
|
|
||||||
s.Root.Readonly = c.HostConfig.ReadonlyRootfs
|
|
||||||
|
|
||||||
err = setMounts(&d, &s, c, ms)
|
|
||||||
assert.Check(t, err)
|
assert.Check(t, err)
|
||||||
|
|
||||||
// Find the /dev/shm mount in ms, check it does not have ro
|
// Find the /dev/shm mount in ms, check it does not have ro
|
||||||
|
@ -88,6 +105,37 @@ func TestIpcPrivateVsReadonly(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSysctlOverride ensures that any implicit sysctls (such as
|
||||||
|
// Config.Domainname) are overridden by an explicit sysctl in the HostConfig.
|
||||||
|
func TestSysctlOverride(t *testing.T) {
|
||||||
|
c := &container.Container{
|
||||||
|
Config: &containertypes.Config{
|
||||||
|
Hostname: "foobar",
|
||||||
|
Domainname: "baz.cyphar.com",
|
||||||
|
},
|
||||||
|
HostConfig: &containertypes.HostConfig{
|
||||||
|
Sysctls: map[string]string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
d := setupFakeDaemon(t, c)
|
||||||
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
|
// Ensure that the implicit sysctl is set correctly.
|
||||||
|
s, err := d.createSpec(c)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, s.Hostname, "foobar")
|
||||||
|
assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.Config.Domainname)
|
||||||
|
|
||||||
|
// Set an explicit sysctl.
|
||||||
|
c.HostConfig.Sysctls["kernel.domainname"] = "foobar.net"
|
||||||
|
assert.Assert(t, c.HostConfig.Sysctls["kernel.domainname"] != c.Config.Domainname)
|
||||||
|
|
||||||
|
s, err = d.createSpec(c)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, s.Hostname, "foobar")
|
||||||
|
assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.HostConfig.Sysctls["kernel.domainname"])
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetSourceMount(t *testing.T) {
|
func TestGetSourceMount(t *testing.T) {
|
||||||
// must be able to find source mount for /
|
// must be able to find source mount for /
|
||||||
mnt, _, err := getSourceMount("/")
|
mnt, _, err := getSourceMount("/")
|
||||||
|
|
|
@ -49,3 +49,44 @@ func TestKernelTCPMemory(t *testing.T) {
|
||||||
assert.Equal(t, 0, res.ExitCode)
|
assert.Equal(t, 0, res.ExitCode)
|
||||||
assert.Check(t, is.Equal(strconv.FormatInt(kernelMemoryTCP, 10), strings.TrimSpace(res.Stdout())))
|
assert.Check(t, is.Equal(strconv.FormatInt(kernelMemoryTCP, 10), strings.TrimSpace(res.Stdout())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNISDomainname(t *testing.T) {
|
||||||
|
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||||
|
|
||||||
|
defer setupTest(t)()
|
||||||
|
client := request.NewAPIClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
const (
|
||||||
|
hostname = "foobar"
|
||||||
|
domainname = "baz.cyphar.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
cID := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||||
|
c.Config.Hostname = hostname
|
||||||
|
c.Config.Domainname = domainname
|
||||||
|
})
|
||||||
|
|
||||||
|
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||||
|
|
||||||
|
inspect, err := client.ContainerInspect(ctx, cID)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Check(t, is.Equal(hostname, inspect.Config.Hostname))
|
||||||
|
assert.Check(t, is.Equal(domainname, inspect.Config.Domainname))
|
||||||
|
|
||||||
|
// Check hostname.
|
||||||
|
res, err := container.Exec(ctx, client, cID,
|
||||||
|
[]string{"cat", "/proc/sys/kernel/hostname"})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, is.Len(res.Stderr(), 0))
|
||||||
|
assert.Equal(t, 0, res.ExitCode)
|
||||||
|
assert.Check(t, is.Equal(hostname, strings.TrimSpace(res.Stdout())))
|
||||||
|
|
||||||
|
// Check domainname.
|
||||||
|
res, err = container.Exec(ctx, client, cID,
|
||||||
|
[]string{"cat", "/proc/sys/kernel/domainname"})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Assert(t, is.Len(res.Stderr(), 0))
|
||||||
|
assert.Equal(t, 0, res.ExitCode)
|
||||||
|
assert.Check(t, is.Equal(domainname, strings.TrimSpace(res.Stdout())))
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue