Browse code

Use ID rather than Name to identify a container when sharing namespace

Fix: https://github.com/moby/moby/issues/34307

Signed-off-by: Chen Min <chenmin46@huawei.com>

Chen Min authored on 2017/08/02 04:04:37
Showing 2 changed files
... ...
@@ -64,6 +64,10 @@ const (
64 64
 	cgroupSystemdDriver = "systemd"
65 65
 )
66 66
 
67
+type containerGetter interface {
68
+	GetContainer(string) (*container.Container, error)
69
+}
70
+
67 71
 func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory {
68 72
 	memory := specs.LinuxMemory{}
69 73
 
... ...
@@ -285,6 +289,8 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
285 285
 		hostConfig.IpcMode = containertypes.IpcMode(m)
286 286
 	}
287 287
 
288
+	adaptSharedNamespaceContainer(daemon, hostConfig)
289
+
288 290
 	var err error
289 291
 	opts, err := daemon.generateSecurityOpt(hostConfig)
290 292
 	if err != nil {
... ...
@@ -299,6 +305,36 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
299 299
 	return nil
300 300
 }
301 301
 
302
+// adaptSharedNamespaceContainer replaces container name with its ID in hostConfig.
303
+// To be more precisely, it modifies `container:name` to `container:ID` of PidMode, IpcMode
304
+// and NetworkMode.
305
+//
306
+// When a container shares its namespace with another container, use ID can keep the namespace
307
+// sharing connection between the two containers even the another container is renamed.
308
+func adaptSharedNamespaceContainer(daemon containerGetter, hostConfig *containertypes.HostConfig) {
309
+	containerPrefix := "container:"
310
+	if hostConfig.PidMode.IsContainer() {
311
+		pidContainer := hostConfig.PidMode.Container()
312
+		// if there is any error returned here, we just ignore it and leave it to be
313
+		// handled in the following logic
314
+		if c, err := daemon.GetContainer(pidContainer); err == nil {
315
+			hostConfig.PidMode = containertypes.PidMode(containerPrefix + c.ID)
316
+		}
317
+	}
318
+	if hostConfig.IpcMode.IsContainer() {
319
+		ipcContainer := hostConfig.IpcMode.Container()
320
+		if c, err := daemon.GetContainer(ipcContainer); err == nil {
321
+			hostConfig.IpcMode = containertypes.IpcMode(containerPrefix + c.ID)
322
+		}
323
+	}
324
+	if hostConfig.NetworkMode.IsContainer() {
325
+		netContainer := hostConfig.NetworkMode.ConnectedContainer()
326
+		if c, err := daemon.GetContainer(netContainer); err == nil {
327
+			hostConfig.NetworkMode = containertypes.NetworkMode(containerPrefix + c.ID)
328
+		}
329
+	}
330
+}
331
+
302 332
 func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) {
303 333
 	warnings := []string{}
304 334
 	fixMemorySwappiness(resources)
... ...
@@ -3,6 +3,7 @@
3 3
 package daemon
4 4
 
5 5
 import (
6
+	"errors"
6 7
 	"io/ioutil"
7 8
 	"os"
8 9
 	"path/filepath"
... ...
@@ -18,6 +19,44 @@ import (
18 18
 	"github.com/docker/docker/volume/store"
19 19
 )
20 20
 
21
+type fakeContainerGetter struct {
22
+	containers map[string]*container.Container
23
+}
24
+
25
+func (f *fakeContainerGetter) GetContainer(cid string) (*container.Container, error) {
26
+	container, ok := f.containers[cid]
27
+	if !ok {
28
+		return nil, errors.New("container not found")
29
+	}
30
+	return container, nil
31
+}
32
+
33
+// Unix test as uses settings which are not available on Windows
34
+func TestAdjustSharedNamespaceContainerName(t *testing.T) {
35
+	fakeID := "abcdef1234567890"
36
+	hostConfig := &containertypes.HostConfig{
37
+		IpcMode:     containertypes.IpcMode("container:base"),
38
+		PidMode:     containertypes.PidMode("container:base"),
39
+		NetworkMode: containertypes.NetworkMode("container:base"),
40
+	}
41
+	containerStore := &fakeContainerGetter{}
42
+	containerStore.containers = make(map[string]*container.Container)
43
+	containerStore.containers["base"] = &container.Container{
44
+		ID: fakeID,
45
+	}
46
+
47
+	adaptSharedNamespaceContainer(containerStore, hostConfig)
48
+	if hostConfig.IpcMode != containertypes.IpcMode("container:"+fakeID) {
49
+		t.Errorf("Expected IpcMode to be container:%s", fakeID)
50
+	}
51
+	if hostConfig.PidMode != containertypes.PidMode("container:"+fakeID) {
52
+		t.Errorf("Expected PidMode to be container:%s", fakeID)
53
+	}
54
+	if hostConfig.NetworkMode != containertypes.NetworkMode("container:"+fakeID) {
55
+		t.Errorf("Expected NetworkMode to be container:%s", fakeID)
56
+	}
57
+}
58
+
21 59
 // Unix test as uses settings which are not available on Windows
22 60
 func TestAdjustCPUShares(t *testing.T) {
23 61
 	tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-")