Browse code

Update port info on network connect/disconnect

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2016/05/26 05:47:38
Showing 3 changed files
... ...
@@ -660,7 +660,8 @@ func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
660 660
 	return pm, nil
661 661
 }
662 662
 
663
-func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
663
+// GetSandboxPortMapInfo retrieves the current port-mapping programmed for the given sandbox
664
+func GetSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
664 665
 	pm := nat.PortMap{}
665 666
 	if sb == nil {
666 667
 		return pm
... ...
@@ -817,7 +818,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
817 817
 	}
818 818
 
819 819
 	// Port-mapping rules belong to the container & applicable only to non-internal networks
820
-	portmaps := getSandboxPortMapInfo(sb)
820
+	portmaps := GetSandboxPortMapInfo(sb)
821 821
 	if n.Info().Internal() || len(portmaps) > 0 {
822 822
 		return createOptions, nil
823 823
 	}
... ...
@@ -27,6 +27,7 @@ var (
27 27
 	// ErrRootFSReadOnly is returned when a container
28 28
 	// rootfs is marked readonly.
29 29
 	ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
30
+	getPortMapInfo    = container.GetSandboxPortMapInfo
30 31
 )
31 32
 
32 33
 func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
... ...
@@ -587,6 +588,8 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
587 587
 		return fmt.Errorf("Updating join info failed: %v", err)
588 588
 	}
589 589
 
590
+	container.NetworkSettings.Ports = getPortMapInfo(sb)
591
+
590 592
 	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
591 593
 	return nil
592 594
 }
... ...
@@ -639,6 +642,8 @@ func disconnectFromNetwork(container *container.Container, n libnetwork.Network,
639 639
 		return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
640 640
 	}
641 641
 
642
+	container.NetworkSettings.Ports = getPortMapInfo(sbox)
643
+
642 644
 	if err := ep.Delete(false); err != nil {
643 645
 		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
644 646
 	}
... ...
@@ -1110,6 +1110,52 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C)
1110 1110
 	dockerCmd(c, "network", "connect", "test1", "c1")
1111 1111
 }
1112 1112
 
1113
+func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) {
1114
+	chk := checker.Equals
1115
+	if !mustBeEqual {
1116
+		chk = checker.Not(checker.Equals)
1117
+	}
1118
+	currentMapping, _ := dockerCmd(c, "port", container, port)
1119
+	c.Assert(currentMapping, chk, originalMapping)
1120
+}
1121
+
1122
+func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) {
1123
+	// Connect and disconnect a container with explicit and non-explicit
1124
+	// host port mapping to/from networks which do cause and do not cause
1125
+	// the container default gateway to change, and verify docker port cmd
1126
+	// returns congruent information
1127
+	testRequires(c, NotArm)
1128
+	cnt := "c1"
1129
+	dockerCmd(c, "network", "create", "aaa")
1130
+	dockerCmd(c, "network", "create", "ccc")
1131
+
1132
+	dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top")
1133
+	c.Assert(waitRun(cnt), check.IsNil)
1134
+	curPortMap, _ := dockerCmd(c, "port", cnt, "70")
1135
+	curExplPortMap, _ := dockerCmd(c, "port", cnt, "90")
1136
+
1137
+	// Connect to a network which causes the container's default gw switch
1138
+	dockerCmd(c, "network", "connect", "aaa", cnt)
1139
+	verifyPortMap(c, cnt, "70", curPortMap, false)
1140
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
1141
+
1142
+	// Read current mapping
1143
+	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
1144
+
1145
+	// Disconnect from a network which causes the container's default gw switch
1146
+	dockerCmd(c, "network", "disconnect", "aaa", cnt)
1147
+	verifyPortMap(c, cnt, "70", curPortMap, false)
1148
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
1149
+
1150
+	// Read current mapping
1151
+	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
1152
+
1153
+	// Connect to a network which does not cause the container's default gw switch
1154
+	dockerCmd(c, "network", "connect", "ccc", cnt)
1155
+	verifyPortMap(c, cnt, "70", curPortMap, true)
1156
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
1157
+}
1158
+
1113 1159
 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
1114 1160
 	macAddress := "02:42:ac:11:00:02"
1115 1161
 	dockerCmd(c, "network", "create", "mynetwork")