github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/oci_linux_test.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	containertypes "github.com/docker/docker/api/types/container"
    10  	"github.com/docker/docker/container"
    11  	"github.com/docker/docker/daemon/config"
    12  	"github.com/docker/docker/daemon/network"
    13  	"github.com/docker/docker/pkg/containerfs"
    14  	"github.com/docker/docker/pkg/idtools"
    15  	"github.com/docker/libnetwork"
    16  	"gotest.tools/v3/assert"
    17  	is "gotest.tools/v3/assert/cmp"
    18  )
    19  
    20  func setupFakeDaemon(t *testing.T, c *container.Container) *Daemon {
    21  	root, err := ioutil.TempDir("", "oci_linux_test-root")
    22  	assert.NilError(t, err)
    23  
    24  	rootfs := filepath.Join(root, "rootfs")
    25  	err = os.MkdirAll(rootfs, 0755)
    26  	assert.NilError(t, err)
    27  
    28  	netController, err := libnetwork.New()
    29  	assert.NilError(t, err)
    30  
    31  	d := &Daemon{
    32  		// some empty structs to avoid getting a panic
    33  		// caused by a null pointer dereference
    34  		idMapping:     &idtools.IdentityMapping{},
    35  		configStore:   &config.Config{},
    36  		linkIndex:     newLinkIndex(),
    37  		netController: netController,
    38  	}
    39  
    40  	c.Root = root
    41  	c.BaseFS = containerfs.NewLocalContainerFS(rootfs)
    42  
    43  	if c.Config == nil {
    44  		c.Config = new(containertypes.Config)
    45  	}
    46  	if c.HostConfig == nil {
    47  		c.HostConfig = new(containertypes.HostConfig)
    48  	}
    49  	if c.NetworkSettings == nil {
    50  		c.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)}
    51  	}
    52  
    53  	return d
    54  }
    55  
    56  func cleanupFakeContainer(c *container.Container) {
    57  	_ = os.RemoveAll(c.Root)
    58  }
    59  
    60  // TestTmpfsDevShmNoDupMount checks that a user-specified /dev/shm tmpfs
    61  // mount (as in "docker run --tmpfs /dev/shm:rw,size=NNN") does not result
    62  // in "Duplicate mount point" error from the engine.
    63  // https://github.com/moby/moby/issues/35455
    64  func TestTmpfsDevShmNoDupMount(t *testing.T) {
    65  	c := &container.Container{
    66  		ShmPath: "foobar", // non-empty, for c.IpcMounts() to work
    67  		HostConfig: &containertypes.HostConfig{
    68  			IpcMode: containertypes.IpcMode("shareable"), // default mode
    69  			// --tmpfs /dev/shm:rw,exec,size=NNN
    70  			Tmpfs: map[string]string{
    71  				"/dev/shm": "rw,exec,size=1g",
    72  			},
    73  		},
    74  	}
    75  	d := setupFakeDaemon(t, c)
    76  	defer cleanupFakeContainer(c)
    77  
    78  	_, err := d.createSpec(c)
    79  	assert.Check(t, err)
    80  }
    81  
    82  // TestIpcPrivateVsReadonly checks that in case of IpcMode: private
    83  // and ReadonlyRootfs: true (as in "docker run --ipc private --read-only")
    84  // the resulting /dev/shm mount is NOT made read-only.
    85  // https://github.com/moby/moby/issues/36503
    86  func TestIpcPrivateVsReadonly(t *testing.T) {
    87  	c := &container.Container{
    88  		HostConfig: &containertypes.HostConfig{
    89  			IpcMode:        containertypes.IpcMode("private"),
    90  			ReadonlyRootfs: true,
    91  		},
    92  	}
    93  	d := setupFakeDaemon(t, c)
    94  	defer cleanupFakeContainer(c)
    95  
    96  	s, err := d.createSpec(c)
    97  	assert.Check(t, err)
    98  
    99  	// Find the /dev/shm mount in ms, check it does not have ro
   100  	for _, m := range s.Mounts {
   101  		if m.Destination != "/dev/shm" {
   102  			continue
   103  		}
   104  		assert.Check(t, is.Equal(false, inSlice(m.Options, "ro")))
   105  	}
   106  }
   107  
   108  // TestSysctlOverride ensures that any implicit sysctls (such as
   109  // Config.Domainname) are overridden by an explicit sysctl in the HostConfig.
   110  func TestSysctlOverride(t *testing.T) {
   111  	c := &container.Container{
   112  		Config: &containertypes.Config{
   113  			Hostname:   "foobar",
   114  			Domainname: "baz.cyphar.com",
   115  		},
   116  		HostConfig: &containertypes.HostConfig{
   117  			NetworkMode: "bridge",
   118  			Sysctls:     map[string]string{},
   119  			UsernsMode:  "host",
   120  		},
   121  	}
   122  	d := setupFakeDaemon(t, c)
   123  	defer cleanupFakeContainer(c)
   124  
   125  	// Ensure that the implicit sysctl is set correctly.
   126  	s, err := d.createSpec(c)
   127  	assert.NilError(t, err)
   128  	assert.Equal(t, s.Hostname, "foobar")
   129  	assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.Config.Domainname)
   130  	if sysctlExists("net.ipv4.ip_unprivileged_port_start") {
   131  		assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "0")
   132  	}
   133  	if sysctlExists("net.ipv4.ping_group_range") {
   134  		assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
   135  	}
   136  
   137  	// Set an explicit sysctl.
   138  	c.HostConfig.Sysctls["kernel.domainname"] = "foobar.net"
   139  	assert.Assert(t, c.HostConfig.Sysctls["kernel.domainname"] != c.Config.Domainname)
   140  	c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
   141  
   142  	s, err = d.createSpec(c)
   143  	assert.NilError(t, err)
   144  	assert.Equal(t, s.Hostname, "foobar")
   145  	assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.HostConfig.Sysctls["kernel.domainname"])
   146  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
   147  }
   148  
   149  // TestSysctlOverrideHost ensures that any implicit network sysctls are not set
   150  // with host networking
   151  func TestSysctlOverrideHost(t *testing.T) {
   152  	c := &container.Container{
   153  		Config: &containertypes.Config{},
   154  		HostConfig: &containertypes.HostConfig{
   155  			NetworkMode: "host",
   156  			Sysctls:     map[string]string{},
   157  			UsernsMode:  "host",
   158  		},
   159  	}
   160  	d := setupFakeDaemon(t, c)
   161  	defer cleanupFakeContainer(c)
   162  
   163  	// Ensure that the implicit sysctl is not set
   164  	s, err := d.createSpec(c)
   165  	assert.NilError(t, err)
   166  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "")
   167  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "")
   168  
   169  	// Set an explicit sysctl.
   170  	c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
   171  
   172  	s, err = d.createSpec(c)
   173  	assert.NilError(t, err)
   174  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
   175  }
   176  
   177  func TestGetSourceMount(t *testing.T) {
   178  	// must be able to find source mount for /
   179  	mnt, _, err := getSourceMount("/")
   180  	assert.NilError(t, err)
   181  	assert.Equal(t, mnt, "/")
   182  
   183  	// must be able to find source mount for current directory
   184  	cwd, err := os.Getwd()
   185  	assert.NilError(t, err)
   186  	_, _, err = getSourceMount(cwd)
   187  	assert.NilError(t, err)
   188  }