Browse code

Address code review feedback

Also make sure we copy the joining containers hosts and resolv.conf with
the hostname if we are joining it's network stack.
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/05/03 08:59:28
Showing 3 changed files
... ...
@@ -338,7 +338,7 @@ func populateCommand(c *Container, env []string) error {
338 338
 		Interface: nil,
339 339
 	}
340 340
 
341
-	parts := strings.SplitN(c.hostConfig.NetworkMode, ":", 2)
341
+	parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
342 342
 	switch parts[0] {
343 343
 	case "none":
344 344
 	case "host":
... ...
@@ -354,9 +354,9 @@ func populateCommand(c *Container, env []string) error {
354 354
 			}
355 355
 		}
356 356
 	case "container":
357
-		nc := c.daemon.Get(parts[1])
358
-		if nc == nil {
359
-			return fmt.Errorf("no such container to join network: %q", parts[1])
357
+		nc, err := c.getNetworkedContainer()
358
+		if err != nil {
359
+			return err
360 360
 		}
361 361
 		en.ContainerID = nc.ID
362 362
 	default:
... ...
@@ -536,7 +536,8 @@ ff02::2		ip6-allrouters
536 536
 }
537 537
 
538 538
 func (container *Container) allocateNetwork() error {
539
-	if container.Config.NetworkDisabled || container.hostConfig.NetworkMode == "host" {
539
+	mode := container.hostConfig.NetworkMode
540
+	if container.Config.NetworkDisabled || mode.IsContainer() || mode.IsHost() {
540 541
 		return nil
541 542
 	}
542 543
 
... ...
@@ -1045,7 +1046,7 @@ func (container *Container) setupContainerDns() error {
1045 1045
 
1046 1046
 func (container *Container) initializeNetworking() error {
1047 1047
 	var err error
1048
-	if container.hostConfig.NetworkMode == "host" {
1048
+	if container.hostConfig.NetworkMode.IsHost() {
1049 1049
 		container.Config.Hostname, err = os.Hostname()
1050 1050
 		if err != nil {
1051 1051
 			return err
... ...
@@ -1059,6 +1060,16 @@ func (container *Container) initializeNetworking() error {
1059 1059
 		container.HostsPath = "/etc/hosts"
1060 1060
 
1061 1061
 		container.buildHostname()
1062
+	} else if container.hostConfig.NetworkMode.IsContainer() {
1063
+		// we need to get the hosts files from the container to join
1064
+		nc, err := container.getNetworkedContainer()
1065
+		if err != nil {
1066
+			return err
1067
+		}
1068
+		container.HostsPath = nc.HostsPath
1069
+		container.ResolvConfPath = nc.ResolvConfPath
1070
+		container.Config.Hostname = nc.Config.Hostname
1071
+		container.Config.Domainname = nc.Config.Domainname
1062 1072
 	} else if container.daemon.config.DisableNetwork {
1063 1073
 		container.Config.NetworkDisabled = true
1064 1074
 		container.buildHostnameAndHostsFiles("127.0.1.1")
... ...
@@ -1268,3 +1279,20 @@ func (container *Container) GetMountLabel() string {
1268 1268
 	}
1269 1269
 	return container.MountLabel
1270 1270
 }
1271
+
1272
+func (container *Container) getNetworkedContainer() (*Container, error) {
1273
+	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
1274
+	switch parts[0] {
1275
+	case "container":
1276
+		nc := container.daemon.Get(parts[1])
1277
+		if nc == nil {
1278
+			return nil, fmt.Errorf("no such container to join network: %s", parts[1])
1279
+		}
1280
+		if !nc.State.IsRunning() {
1281
+			return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
1282
+		}
1283
+		return nc, nil
1284
+	default:
1285
+		return nil, fmt.Errorf("network mode not set to container")
1286
+	}
1287
+}
... ...
@@ -1,11 +1,24 @@
1 1
 package runconfig
2 2
 
3 3
 import (
4
+	"strings"
5
+
4 6
 	"github.com/dotcloud/docker/engine"
5 7
 	"github.com/dotcloud/docker/nat"
6 8
 	"github.com/dotcloud/docker/utils"
7 9
 )
8 10
 
11
+type NetworkMode string
12
+
13
+func (n NetworkMode) IsHost() bool {
14
+	return n == "host"
15
+}
16
+
17
+func (n NetworkMode) IsContainer() bool {
18
+	parts := strings.SplitN(string(n), ":", 2)
19
+	return len(parts) > 1 && parts[0] == "container"
20
+}
21
+
9 22
 type HostConfig struct {
10 23
 	Binds           []string
11 24
 	ContainerIDFile string
... ...
@@ -17,7 +30,7 @@ type HostConfig struct {
17 17
 	Dns             []string
18 18
 	DnsSearch       []string
19 19
 	VolumesFrom     []string
20
-	NetworkMode     string
20
+	NetworkMode     NetworkMode
21 21
 }
22 22
 
23 23
 func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
... ...
@@ -25,7 +38,7 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
25 25
 		ContainerIDFile: job.Getenv("ContainerIDFile"),
26 26
 		Privileged:      job.GetenvBool("Privileged"),
27 27
 		PublishAllPorts: job.GetenvBool("PublishAllPorts"),
28
-		NetworkMode:     job.Getenv("NetworkMode"),
28
+		NetworkMode:     NetworkMode(job.Getenv("NetworkMode")),
29 29
 	}
30 30
 	job.GetenvJson("LxcConf", &hostConfig.LxcConf)
31 31
 	job.GetenvJson("PortBindings", &hostConfig.PortBindings)
... ...
@@ -62,7 +62,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
62 62
 		flUser            = cmd.String([]string{"u", "-user"}, "", "Username or UID")
63 63
 		flWorkingDir      = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
64 64
 		flCpuShares       = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
65
-		flNetMode         = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container ('bridge': creates a new network stack for the container on the docker bridge, 'none': no networking for this container, 'container:name_or_id': reuses another container network stack)")
65
+		flNetMode         = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container ('bridge': creates a new network stack for the container on the docker bridge, 'none': no networking for this container, 'container:<name|id>': reuses another container network stack)")
66 66
 		// For documentation purpose
67 67
 		_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
68 68
 		_ = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
... ...
@@ -200,7 +200,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
200 200
 
201 201
 	netMode, err := parseNetMode(*flNetMode)
202 202
 	if err != nil {
203
-		return nil, nil, cmd, fmt.Errorf("-net: invalid net mode: %v", err)
203
+		return nil, nil, cmd, fmt.Errorf("--net: invalid net mode: %v", err)
204 204
 	}
205 205
 
206 206
 	config := &Config{
... ...
@@ -282,19 +282,16 @@ func parseKeyValueOpts(opts opts.ListOpts) ([]utils.KeyValuePair, error) {
282 282
 	return out, nil
283 283
 }
284 284
 
285
-func parseNetMode(netMode string) (string, error) {
285
+func parseNetMode(netMode string) (NetworkMode, error) {
286 286
 	parts := strings.Split(netMode, ":")
287 287
 	switch mode := parts[0]; mode {
288
-	case "bridge", "none":
289
-		return mode, nil
288
+	case "bridge", "none", "host":
290 289
 	case "container":
291 290
 		if len(parts) < 2 || parts[1] == "" {
292
-			return "", fmt.Errorf("'container:' netmode requires a container id or name", netMode)
291
+			return "", fmt.Errorf("invalid container format container:<name|id>")
293 292
 		}
294
-		return netMode, nil
295
-	case "host":
296
-		return netMode, nil
297 293
 	default:
298
-		return "", fmt.Errorf("invalid netmode: %q", netMode)
294
+		return "", fmt.Errorf("invalid --net: %s", netMode)
299 295
 	}
296
+	return NetworkMode(netMode), nil
300 297
 }