Browse code

Update port info on network connect/disconnect

Signed-off-by: Alessandro Boch <aboch@docker.com>
(cherry picked from commit f198dfd856ca6125ef50b11d9d698550d66c9d4e)

Alessandro Boch authored on 2016/05/26 05:47:38
Showing 3 changed files
... ...
@@ -667,7 +667,8 @@ func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
667 667
 	return pm, nil
668 668
 }
669 669
 
670
-func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
670
+// GetSandboxPortMapInfo retrieves the current port-mapping programmed for the given sandbox
671
+func GetSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
671 672
 	pm := nat.PortMap{}
672 673
 	if sb == nil {
673 674
 		return pm
... ...
@@ -824,7 +825,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
824 824
 	}
825 825
 
826 826
 	// Port-mapping rules belong to the container & applicable only to non-internal networks
827
-	portmaps := getSandboxPortMapInfo(sb)
827
+	portmaps := GetSandboxPortMapInfo(sb)
828 828
 	if n.Info().Internal() || len(portmaps) > 0 {
829 829
 		return createOptions, nil
830 830
 	}
... ...
@@ -26,6 +26,7 @@ var (
26 26
 	// ErrRootFSReadOnly is returned when a container
27 27
 	// rootfs is marked readonly.
28 28
 	ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
29
+	getPortMapInfo    = container.GetSandboxPortMapInfo
29 30
 )
30 31
 
31 32
 func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
... ...
@@ -581,6 +582,8 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
581 581
 		return fmt.Errorf("Updating join info failed: %v", err)
582 582
 	}
583 583
 
584
+	container.NetworkSettings.Ports = getPortMapInfo(sb)
585
+
584 586
 	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
585 587
 	return nil
586 588
 }
... ...
@@ -633,6 +636,8 @@ func disconnectFromNetwork(container *container.Container, n libnetwork.Network,
633 633
 		return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
634 634
 	}
635 635
 
636
+	container.NetworkSettings.Ports = getPortMapInfo(sbox)
637
+
636 638
 	if err := ep.Delete(false); err != nil {
637 639
 		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
638 640
 	}
... ...
@@ -1080,6 +1080,52 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C)
1080 1080
 	dockerCmd(c, "network", "connect", "test1", "c1")
1081 1081
 }
1082 1082
 
1083
+func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) {
1084
+	chk := checker.Equals
1085
+	if !mustBeEqual {
1086
+		chk = checker.Not(checker.Equals)
1087
+	}
1088
+	currentMapping, _ := dockerCmd(c, "port", container, port)
1089
+	c.Assert(currentMapping, chk, originalMapping)
1090
+}
1091
+
1092
+func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) {
1093
+	// Connect and disconnect a container with explicit and non-explicit
1094
+	// host port mapping to/from networks which do cause and do not cause
1095
+	// the container default gateway to change, and verify docker port cmd
1096
+	// returns congruent information
1097
+	testRequires(c, NotArm)
1098
+	cnt := "c1"
1099
+	dockerCmd(c, "network", "create", "aaa")
1100
+	dockerCmd(c, "network", "create", "ccc")
1101
+
1102
+	dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top")
1103
+	c.Assert(waitRun(cnt), check.IsNil)
1104
+	curPortMap, _ := dockerCmd(c, "port", cnt, "70")
1105
+	curExplPortMap, _ := dockerCmd(c, "port", cnt, "90")
1106
+
1107
+	// Connect to a network which causes the container's default gw switch
1108
+	dockerCmd(c, "network", "connect", "aaa", cnt)
1109
+	verifyPortMap(c, cnt, "70", curPortMap, false)
1110
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
1111
+
1112
+	// Read current mapping
1113
+	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
1114
+
1115
+	// Disconnect from a network which causes the container's default gw switch
1116
+	dockerCmd(c, "network", "disconnect", "aaa", cnt)
1117
+	verifyPortMap(c, cnt, "70", curPortMap, false)
1118
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
1119
+
1120
+	// Read current mapping
1121
+	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
1122
+
1123
+	// Connect to a network which does not cause the container's default gw switch
1124
+	dockerCmd(c, "network", "connect", "ccc", cnt)
1125
+	verifyPortMap(c, cnt, "70", curPortMap, true)
1126
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
1127
+}
1128
+
1083 1129
 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
1084 1130
 	macAddress := "02:42:ac:11:00:02"
1085 1131
 	dockerCmd(c, "network", "create", "mynetwork")