Signed-off-by: Arash Deshmeh <adeshmeh@ca.ibm.com>
| 1 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,81 +0,0 @@ |
| 1 |
-// build +linux |
|
| 2 |
-package main |
|
| 3 |
- |
|
| 4 |
-import ( |
|
| 5 |
- "bufio" |
|
| 6 |
- "context" |
|
| 7 |
- "io/ioutil" |
|
| 8 |
- "os" |
|
| 9 |
- "strings" |
|
| 10 |
- |
|
| 11 |
- "github.com/docker/docker/api/types" |
|
| 12 |
- "github.com/docker/docker/api/types/container" |
|
| 13 |
- "github.com/docker/docker/integration-cli/checker" |
|
| 14 |
- "github.com/docker/docker/integration-cli/cli" |
|
| 15 |
- "github.com/go-check/check" |
|
| 16 |
-) |
|
| 17 |
- |
|
| 18 |
-/* testIpcCheckDevExists checks whether a given mount (identified by its |
|
| 19 |
- * major:minor pair from /proc/self/mountinfo) exists on the host system. |
|
| 20 |
- * |
|
| 21 |
- * The format of /proc/self/mountinfo is like: |
|
| 22 |
- * |
|
| 23 |
- * 29 23 0:24 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw |
|
| 24 |
- * ^^^^\ |
|
| 25 |
- * - this is the minor:major we look for |
|
| 26 |
- */ |
|
| 27 |
-func testIpcCheckDevExists(mm string) (bool, error) {
|
|
| 28 |
- f, err := os.Open("/proc/self/mountinfo")
|
|
| 29 |
- if err != nil {
|
|
| 30 |
- return false, err |
|
| 31 |
- } |
|
| 32 |
- defer f.Close() |
|
| 33 |
- |
|
| 34 |
- s := bufio.NewScanner(f) |
|
| 35 |
- for s.Scan() {
|
|
| 36 |
- fields := strings.Fields(s.Text()) |
|
| 37 |
- if len(fields) < 7 {
|
|
| 38 |
- continue |
|
| 39 |
- } |
|
| 40 |
- if fields[2] == mm {
|
|
| 41 |
- return true, nil |
|
| 42 |
- } |
|
| 43 |
- } |
|
| 44 |
- |
|
| 45 |
- return false, s.Err() |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-/* TestAPIIpcModeHost checks that a container created with --ipc host |
|
| 49 |
- * can use IPC of the host system. |
|
| 50 |
- */ |
|
| 51 |
-func (s *DockerSuite) TestAPIIpcModeHost(c *check.C) {
|
|
| 52 |
- testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace) |
|
| 53 |
- |
|
| 54 |
- cfg := container.Config{
|
|
| 55 |
- Image: "busybox", |
|
| 56 |
- Cmd: []string{"top"},
|
|
| 57 |
- } |
|
| 58 |
- hostCfg := container.HostConfig{
|
|
| 59 |
- IpcMode: container.IpcMode("host"),
|
|
| 60 |
- } |
|
| 61 |
- ctx := context.Background() |
|
| 62 |
- |
|
| 63 |
- client := testEnv.APIClient() |
|
| 64 |
- resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "") |
|
| 65 |
- c.Assert(err, checker.IsNil) |
|
| 66 |
- c.Assert(len(resp.Warnings), checker.Equals, 0) |
|
| 67 |
- name := resp.ID |
|
| 68 |
- |
|
| 69 |
- err = client.ContainerStart(ctx, name, types.ContainerStartOptions{})
|
|
| 70 |
- c.Assert(err, checker.IsNil) |
|
| 71 |
- |
|
| 72 |
- // check that IPC is shared |
|
| 73 |
- // 1. create a file inside container |
|
| 74 |
- cli.DockerCmd(c, "exec", name, "sh", "-c", "printf covfefe > /dev/shm/."+name) |
|
| 75 |
- // 2. check it's the same on the host |
|
| 76 |
- bytes, err := ioutil.ReadFile("/dev/shm/." + name)
|
|
| 77 |
- c.Assert(err, checker.IsNil) |
|
| 78 |
- c.Assert(string(bytes), checker.Matches, "^covfefe$") |
|
| 79 |
- // 3. clean up |
|
| 80 |
- cli.DockerCmd(c, "exec", name, "rm", "-f", "/dev/shm/."+name) |
|
| 81 |
-} |
| ... | ... |
@@ -2901,67 +2901,6 @@ func (s *DockerDaemonSuite) TestShmSizeReload(c *check.C) {
|
| 2901 | 2901 |
c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size))
|
| 2902 | 2902 |
} |
| 2903 | 2903 |
|
| 2904 |
-// this is used to test both "private" and "shareable" daemon default ipc modes |
|
| 2905 |
-func testDaemonIpcPrivateShareable(d *daemon.Daemon, c *check.C, mustExist bool) {
|
|
| 2906 |
- name := "test-ipcmode" |
|
| 2907 |
- _, err := d.Cmd("run", "-d", "--name", name, "busybox", "top")
|
|
| 2908 |
- c.Assert(err, checker.IsNil) |
|
| 2909 |
- |
|
| 2910 |
- // get major:minor pair for /dev/shm from container's /proc/self/mountinfo |
|
| 2911 |
- cmd := "awk '($5 == \"/dev/shm\") {printf $3}' /proc/self/mountinfo"
|
|
| 2912 |
- mm, err := d.Cmd("exec", "-i", name, "sh", "-c", cmd)
|
|
| 2913 |
- c.Assert(err, checker.IsNil) |
|
| 2914 |
- c.Assert(mm, checker.Matches, "^[0-9]+:[0-9]+$") |
|
| 2915 |
- |
|
| 2916 |
- exists, err := testIpcCheckDevExists(mm) |
|
| 2917 |
- c.Assert(err, checker.IsNil) |
|
| 2918 |
- c.Logf("[testDaemonIpcPrivateShareable] ipcdev: %v, exists: %v, mustExist: %v\n", mm, exists, mustExist)
|
|
| 2919 |
- c.Assert(exists, checker.Equals, mustExist) |
|
| 2920 |
-} |
|
| 2921 |
- |
|
| 2922 |
-// TestDaemonIpcModeShareable checks that --default-ipc-mode shareable works as intended. |
|
| 2923 |
-func (s *DockerDaemonSuite) TestDaemonIpcModeShareable(c *check.C) {
|
|
| 2924 |
- testRequires(c, DaemonIsLinux, SameHostDaemon) |
|
| 2925 |
- |
|
| 2926 |
- s.d.StartWithBusybox(c, "--default-ipc-mode", "shareable") |
|
| 2927 |
- testDaemonIpcPrivateShareable(s.d, c, true) |
|
| 2928 |
-} |
|
| 2929 |
- |
|
| 2930 |
-// TestDaemonIpcModePrivate checks that --default-ipc-mode private works as intended. |
|
| 2931 |
-func (s *DockerDaemonSuite) TestDaemonIpcModePrivate(c *check.C) {
|
|
| 2932 |
- testRequires(c, DaemonIsLinux, SameHostDaemon) |
|
| 2933 |
- |
|
| 2934 |
- s.d.StartWithBusybox(c, "--default-ipc-mode", "private") |
|
| 2935 |
- testDaemonIpcPrivateShareable(s.d, c, false) |
|
| 2936 |
-} |
|
| 2937 |
- |
|
| 2938 |
-// used to check if an IpcMode given in config works as intended |
|
| 2939 |
-func testDaemonIpcFromConfig(s *DockerDaemonSuite, c *check.C, mode string, mustExist bool) {
|
|
| 2940 |
- f, err := ioutil.TempFile("", "test-daemon-ipc-config")
|
|
| 2941 |
- c.Assert(err, checker.IsNil) |
|
| 2942 |
- defer os.Remove(f.Name()) |
|
| 2943 |
- |
|
| 2944 |
- config := `{"default-ipc-mode": "` + mode + `"}`
|
|
| 2945 |
- _, err = f.WriteString(config) |
|
| 2946 |
- c.Assert(f.Close(), checker.IsNil) |
|
| 2947 |
- c.Assert(err, checker.IsNil) |
|
| 2948 |
- |
|
| 2949 |
- s.d.StartWithBusybox(c, "--config-file", f.Name()) |
|
| 2950 |
- testDaemonIpcPrivateShareable(s.d, c, mustExist) |
|
| 2951 |
-} |
|
| 2952 |
- |
|
| 2953 |
-// TestDaemonIpcModePrivateFromConfig checks that "default-ipc-mode: private" config works as intended. |
|
| 2954 |
-func (s *DockerDaemonSuite) TestDaemonIpcModePrivateFromConfig(c *check.C) {
|
|
| 2955 |
- testRequires(c, DaemonIsLinux, SameHostDaemon) |
|
| 2956 |
- testDaemonIpcFromConfig(s, c, "private", false) |
|
| 2957 |
-} |
|
| 2958 |
- |
|
| 2959 |
-// TestDaemonIpcModeShareableFromConfig checks that "default-ipc-mode: shareable" config works as intended. |
|
| 2960 |
-func (s *DockerDaemonSuite) TestDaemonIpcModeShareableFromConfig(c *check.C) {
|
|
| 2961 |
- testRequires(c, DaemonIsLinux, SameHostDaemon) |
|
| 2962 |
- testDaemonIpcFromConfig(s, c, "shareable", true) |
|
| 2963 |
-} |
|
| 2964 |
- |
|
| 2965 | 2904 |
func testDaemonStartIpcMode(c *check.C, from, mode string, valid bool) {
|
| 2966 | 2905 |
d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) |
| 2967 | 2906 |
c.Logf("Checking IpcMode %s set from %s\n", mode, from)
|
| ... | ... |
@@ -3,6 +3,7 @@ package container // import "github.com/docker/docker/integration/container" |
| 3 | 3 |
import ( |
| 4 | 4 |
"bufio" |
| 5 | 5 |
"context" |
| 6 |
+ "io/ioutil" |
|
| 6 | 7 |
"os" |
| 7 | 8 |
"regexp" |
| 8 | 9 |
"strings" |
| ... | ... |
@@ -11,9 +12,11 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 | 12 |
containertypes "github.com/docker/docker/api/types/container" |
| 13 | 13 |
"github.com/docker/docker/integration/internal/container" |
| 14 |
+ "github.com/docker/docker/internal/test/daemon" |
|
| 14 | 15 |
"github.com/docker/docker/internal/test/request" |
| 15 | 16 |
"gotest.tools/assert" |
| 16 | 17 |
is "gotest.tools/assert/cmp" |
| 18 |
+ "gotest.tools/fs" |
|
| 17 | 19 |
"gotest.tools/skip" |
| 18 | 20 |
) |
| 19 | 21 |
|
| ... | ... |
@@ -179,3 +182,114 @@ func TestAPIIpcModeShareableAndContainer(t *testing.T) {
|
| 179 | 179 |
|
| 180 | 180 |
testIpcContainer(t, "private", false) |
| 181 | 181 |
} |
| 182 |
+ |
|
| 183 |
+/* TestAPIIpcModeHost checks that a container created with --ipc host |
|
| 184 |
+ * can use IPC of the host system. |
|
| 185 |
+ */ |
|
| 186 |
+func TestAPIIpcModeHost(t *testing.T) {
|
|
| 187 |
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon() || testEnv.IsUserNamespace()) |
|
| 188 |
+ |
|
| 189 |
+ cfg := containertypes.Config{
|
|
| 190 |
+ Image: "busybox", |
|
| 191 |
+ Cmd: []string{"top"},
|
|
| 192 |
+ } |
|
| 193 |
+ hostCfg := containertypes.HostConfig{
|
|
| 194 |
+ IpcMode: containertypes.IpcMode("host"),
|
|
| 195 |
+ } |
|
| 196 |
+ ctx := context.Background() |
|
| 197 |
+ |
|
| 198 |
+ client := testEnv.APIClient() |
|
| 199 |
+ resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "") |
|
| 200 |
+ assert.NilError(t, err) |
|
| 201 |
+ assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
|
| 202 |
+ name := resp.ID |
|
| 203 |
+ |
|
| 204 |
+ err = client.ContainerStart(ctx, name, types.ContainerStartOptions{})
|
|
| 205 |
+ assert.NilError(t, err) |
|
| 206 |
+ |
|
| 207 |
+ // check that IPC is shared |
|
| 208 |
+ // 1. create a file inside container |
|
| 209 |
+ _, err = container.Exec(ctx, client, name, []string{"sh", "-c", "printf covfefe > /dev/shm/." + name})
|
|
| 210 |
+ assert.NilError(t, err) |
|
| 211 |
+ // 2. check it's the same on the host |
|
| 212 |
+ bytes, err := ioutil.ReadFile("/dev/shm/." + name)
|
|
| 213 |
+ assert.NilError(t, err) |
|
| 214 |
+ assert.Check(t, is.Equal("covfefe", string(bytes)))
|
|
| 215 |
+ // 3. clean up |
|
| 216 |
+ _, err = container.Exec(ctx, client, name, []string{"rm", "-f", "/dev/shm/." + name})
|
|
| 217 |
+ assert.NilError(t, err) |
|
| 218 |
+} |
|
| 219 |
+ |
|
| 220 |
+// testDaemonIpcPrivateShareable is a helper function to test "private" and "shareable" daemon default ipc modes. |
|
| 221 |
+func testDaemonIpcPrivateShareable(t *testing.T, mustBeShared bool, arg ...string) {
|
|
| 222 |
+ defer setupTest(t)() |
|
| 223 |
+ |
|
| 224 |
+ d := daemon.New(t) |
|
| 225 |
+ d.StartWithBusybox(t, arg...) |
|
| 226 |
+ defer d.Stop(t) |
|
| 227 |
+ |
|
| 228 |
+ client, err := d.NewClient() |
|
| 229 |
+ assert.Check(t, err, "error creating client") |
|
| 230 |
+ |
|
| 231 |
+ cfg := containertypes.Config{
|
|
| 232 |
+ Image: "busybox", |
|
| 233 |
+ Cmd: []string{"top"},
|
|
| 234 |
+ } |
|
| 235 |
+ ctx := context.Background() |
|
| 236 |
+ |
|
| 237 |
+ resp, err := client.ContainerCreate(ctx, &cfg, &containertypes.HostConfig{}, nil, "")
|
|
| 238 |
+ assert.NilError(t, err) |
|
| 239 |
+ assert.Check(t, is.Equal(len(resp.Warnings), 0)) |
|
| 240 |
+ |
|
| 241 |
+ err = client.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
|
|
| 242 |
+ assert.NilError(t, err) |
|
| 243 |
+ |
|
| 244 |
+ // get major:minor pair for /dev/shm from container's /proc/self/mountinfo |
|
| 245 |
+ cmd := "awk '($5 == \"/dev/shm\") {printf $3}' /proc/self/mountinfo"
|
|
| 246 |
+ result, err := container.Exec(ctx, client, resp.ID, []string{"sh", "-c", cmd})
|
|
| 247 |
+ assert.NilError(t, err) |
|
| 248 |
+ mm := result.Combined() |
|
| 249 |
+ assert.Check(t, is.Equal(true, regexp.MustCompile("^[0-9]+:[0-9]+$").MatchString(mm)))
|
|
| 250 |
+ |
|
| 251 |
+ shared, err := testIpcCheckDevExists(mm) |
|
| 252 |
+ assert.NilError(t, err) |
|
| 253 |
+ t.Logf("[testDaemonIpcPrivateShareable] ipcdev: %v, shared: %v, mustBeShared: %v\n", mm, shared, mustBeShared)
|
|
| 254 |
+ assert.Check(t, is.Equal(shared, mustBeShared)) |
|
| 255 |
+} |
|
| 256 |
+ |
|
| 257 |
+// TestDaemonIpcModeShareable checks that --default-ipc-mode shareable works as intended. |
|
| 258 |
+func TestDaemonIpcModeShareable(t *testing.T) {
|
|
| 259 |
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon()) |
|
| 260 |
+ |
|
| 261 |
+ testDaemonIpcPrivateShareable(t, true, "--default-ipc-mode", "shareable") |
|
| 262 |
+} |
|
| 263 |
+ |
|
| 264 |
+// TestDaemonIpcModePrivate checks that --default-ipc-mode private works as intended. |
|
| 265 |
+func TestDaemonIpcModePrivate(t *testing.T) {
|
|
| 266 |
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon()) |
|
| 267 |
+ |
|
| 268 |
+ testDaemonIpcPrivateShareable(t, false, "--default-ipc-mode", "private") |
|
| 269 |
+} |
|
| 270 |
+ |
|
| 271 |
+// used to check if an IpcMode given in config works as intended |
|
| 272 |
+func testDaemonIpcFromConfig(t *testing.T, mode string, mustExist bool) {
|
|
| 273 |
+ config := `{"default-ipc-mode": "` + mode + `"}`
|
|
| 274 |
+ file := fs.NewFile(t, "test-daemon-ipc-config", fs.WithContent(config)) |
|
| 275 |
+ defer file.Remove() |
|
| 276 |
+ |
|
| 277 |
+ testDaemonIpcPrivateShareable(t, mustExist, "--config-file", file.Path()) |
|
| 278 |
+} |
|
| 279 |
+ |
|
| 280 |
+// TestDaemonIpcModePrivateFromConfig checks that "default-ipc-mode: private" config works as intended. |
|
| 281 |
+func TestDaemonIpcModePrivateFromConfig(t *testing.T) {
|
|
| 282 |
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon()) |
|
| 283 |
+ |
|
| 284 |
+ testDaemonIpcFromConfig(t, "private", false) |
|
| 285 |
+} |
|
| 286 |
+ |
|
| 287 |
+// TestDaemonIpcModeShareableFromConfig checks that "default-ipc-mode: shareable" config works as intended. |
|
| 288 |
+func TestDaemonIpcModeShareableFromConfig(t *testing.T) {
|
|
| 289 |
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon()) |
|
| 290 |
+ |
|
| 291 |
+ testDaemonIpcFromConfig(t, "shareable", true) |
|
| 292 |
+} |
| ... | ... |
@@ -145,6 +145,12 @@ func (e *Execution) APIClient() client.APIClient {
|
| 145 | 145 |
return e.client |
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 |
+// IsUserNamespace returns whether the user namespace remapping is enabled |
|
| 149 |
+func (e *Execution) IsUserNamespace() bool {
|
|
| 150 |
+ root := os.Getenv("DOCKER_REMAP_ROOT")
|
|
| 151 |
+ return root != "" |
|
| 152 |
+} |
|
| 153 |
+ |
|
| 148 | 154 |
// EnsureFrozenImagesLinux loads frozen test images into the daemon |
| 149 | 155 |
// if they aren't already loaded |
| 150 | 156 |
func EnsureFrozenImagesLinux(testEnv *Execution) error {
|