github.com/lacework-dev/go-moby@v20.10.12+incompatible/integration/container/run_cgroupns_linux_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "context" 5 "strings" 6 "testing" 7 "time" 8 9 "github.com/docker/docker/client" 10 "github.com/docker/docker/integration/internal/container" 11 "github.com/docker/docker/integration/internal/requirement" 12 "github.com/docker/docker/testutil/daemon" 13 "gotest.tools/v3/assert" 14 is "gotest.tools/v3/assert/cmp" 15 "gotest.tools/v3/poll" 16 "gotest.tools/v3/skip" 17 ) 18 19 // Gets the value of the cgroup namespace for pid 1 of a container 20 func containerCgroupNamespace(ctx context.Context, t *testing.T, client *client.Client, cID string) string { 21 res, err := container.Exec(ctx, client, cID, []string{"readlink", "/proc/1/ns/cgroup"}) 22 assert.NilError(t, err) 23 assert.Assert(t, is.Len(res.Stderr(), 0)) 24 assert.Equal(t, 0, res.ExitCode) 25 return strings.TrimSpace(res.Stdout()) 26 } 27 28 // Bring up a daemon with the specified default cgroup namespace mode, and then create a container with the container options 29 func testRunWithCgroupNs(t *testing.T, daemonNsMode string, containerOpts ...func(*container.TestContainerConfig)) (string, string) { 30 d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode)) 31 client := d.NewClientT(t) 32 ctx := context.Background() 33 34 d.StartWithBusybox(t) 35 defer d.Stop(t) 36 37 cID := container.Run(ctx, t, client, containerOpts...) 38 poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond)) 39 40 daemonCgroup := d.CgroupNamespace(t) 41 containerCgroup := containerCgroupNamespace(ctx, t, client, cID) 42 return containerCgroup, daemonCgroup 43 } 44 45 // Bring up a daemon with the specified default cgroup namespace mode. Create a container with the container options, 46 // expecting an error with the specified string 47 func testCreateFailureWithCgroupNs(t *testing.T, daemonNsMode string, errStr string, containerOpts ...func(*container.TestContainerConfig)) { 48 d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode)) 49 client := d.NewClientT(t) 50 ctx := context.Background() 51 52 d.StartWithBusybox(t) 53 defer d.Stop(t) 54 container.CreateExpectingErr(ctx, t, client, errStr, containerOpts...) 55 } 56 57 func TestCgroupNamespacesRun(t *testing.T) { 58 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 59 skip.If(t, testEnv.IsRemoteDaemon()) 60 skip.If(t, !requirement.CgroupNamespacesEnabled()) 61 62 // When the daemon defaults to private cgroup namespaces, containers launched 63 // should be in their own private cgroup namespace by default 64 containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private") 65 assert.Assert(t, daemonCgroup != containerCgroup) 66 } 67 68 func TestCgroupNamespacesRunPrivileged(t *testing.T) { 69 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 70 skip.If(t, testEnv.IsRemoteDaemon()) 71 skip.If(t, !requirement.CgroupNamespacesEnabled()) 72 skip.If(t, testEnv.DaemonInfo.CgroupVersion == "2", "on cgroup v2, privileged containers use private cgroupns") 73 74 // When the daemon defaults to private cgroup namespaces, privileged containers 75 // launched should not be inside their own cgroup namespaces 76 containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithPrivileged(true)) 77 assert.Assert(t, daemonCgroup == containerCgroup) 78 } 79 80 func TestCgroupNamespacesRunDaemonHostMode(t *testing.T) { 81 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 82 skip.If(t, testEnv.IsRemoteDaemon()) 83 skip.If(t, !requirement.CgroupNamespacesEnabled()) 84 85 // When the daemon defaults to host cgroup namespaces, containers 86 // launched should not be inside their own cgroup namespaces 87 containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "host") 88 assert.Assert(t, daemonCgroup == containerCgroup) 89 } 90 91 func TestCgroupNamespacesRunHostMode(t *testing.T) { 92 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 93 skip.If(t, testEnv.IsRemoteDaemon()) 94 skip.If(t, !requirement.CgroupNamespacesEnabled()) 95 96 // When the daemon defaults to private cgroup namespaces, containers launched 97 // with a cgroup ns mode of "host" should not be inside their own cgroup namespaces 98 containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithCgroupnsMode("host")) 99 assert.Assert(t, daemonCgroup == containerCgroup) 100 } 101 102 func TestCgroupNamespacesRunPrivateMode(t *testing.T) { 103 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 104 skip.If(t, testEnv.IsRemoteDaemon()) 105 skip.If(t, !requirement.CgroupNamespacesEnabled()) 106 107 // When the daemon defaults to private cgroup namespaces, containers launched 108 // with a cgroup ns mode of "private" should be inside their own cgroup namespaces 109 containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithCgroupnsMode("private")) 110 assert.Assert(t, daemonCgroup != containerCgroup) 111 } 112 113 func TestCgroupNamespacesRunPrivilegedAndPrivate(t *testing.T) { 114 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 115 skip.If(t, testEnv.IsRemoteDaemon()) 116 skip.If(t, !requirement.CgroupNamespacesEnabled()) 117 118 containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithPrivileged(true), container.WithCgroupnsMode("private")) 119 assert.Assert(t, daemonCgroup != containerCgroup) 120 } 121 122 func TestCgroupNamespacesRunInvalidMode(t *testing.T) { 123 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 124 skip.If(t, testEnv.IsRemoteDaemon()) 125 skip.If(t, !requirement.CgroupNamespacesEnabled()) 126 127 // An invalid cgroup namespace mode should return an error on container creation 128 errStr := "invalid cgroup namespace mode: invalid" 129 testCreateFailureWithCgroupNs(t, "private", errStr, container.WithCgroupnsMode("invalid")) 130 } 131 132 // Clients before 1.40 expect containers to be created in the host cgroup namespace, 133 // regardless of the default setting of the daemon, unless running with cgroup v2 134 func TestCgroupNamespacesRunOlderClient(t *testing.T) { 135 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 136 skip.If(t, testEnv.IsRemoteDaemon()) 137 skip.If(t, !requirement.CgroupNamespacesEnabled()) 138 139 d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode("private")) 140 client := d.NewClientT(t, client.WithVersion("1.39")) 141 142 ctx := context.Background() 143 d.StartWithBusybox(t) 144 defer d.Stop(t) 145 146 cID := container.Run(ctx, t, client) 147 poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond)) 148 149 daemonCgroup := d.CgroupNamespace(t) 150 containerCgroup := containerCgroupNamespace(ctx, t, client, cID) 151 if testEnv.DaemonInfo.CgroupVersion != "2" { 152 assert.Assert(t, daemonCgroup == containerCgroup) 153 } else { 154 assert.Assert(t, daemonCgroup != containerCgroup) 155 } 156 }