Ver código fonte

Update port info on network connect/disconnect

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 9 anos atrás
pai
commit
f198dfd856

+ 3 - 2
container/container.go

@@ -660,7 +660,8 @@ func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
 	return pm, nil
 	return pm, nil
 }
 }
 
 
-func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
+// GetSandboxPortMapInfo retrieves the current port-mapping programmed for the given sandbox
+func GetSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
 	pm := nat.PortMap{}
 	pm := nat.PortMap{}
 	if sb == nil {
 	if sb == nil {
 		return pm
 		return pm
@@ -817,7 +818,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
 	}
 	}
 
 
 	// Port-mapping rules belong to the container & applicable only to non-internal networks
 	// Port-mapping rules belong to the container & applicable only to non-internal networks
-	portmaps := getSandboxPortMapInfo(sb)
+	portmaps := GetSandboxPortMapInfo(sb)
 	if n.Info().Internal() || len(portmaps) > 0 {
 	if n.Info().Internal() || len(portmaps) > 0 {
 		return createOptions, nil
 		return createOptions, nil
 	}
 	}

+ 5 - 0
daemon/container_operations.go

@@ -27,6 +27,7 @@ var (
 	// ErrRootFSReadOnly is returned when a container
 	// ErrRootFSReadOnly is returned when a container
 	// rootfs is marked readonly.
 	// rootfs is marked readonly.
 	ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
 	ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
+	getPortMapInfo    = container.GetSandboxPortMapInfo
 )
 )
 
 
 func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
 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
 		return fmt.Errorf("Updating join info failed: %v", err)
 		return fmt.Errorf("Updating join info failed: %v", err)
 	}
 	}
 
 
+	container.NetworkSettings.Ports = getPortMapInfo(sb)
+
 	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
 	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
 	return nil
 	return nil
 }
 }
@@ -639,6 +642,8 @@ func disconnectFromNetwork(container *container.Container, n libnetwork.Network,
 		return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
 		return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
 	}
 	}
 
 
+	container.NetworkSettings.Ports = getPortMapInfo(sbox)
+
 	if err := ep.Delete(false); err != nil {
 	if err := ep.Delete(false); err != nil {
 		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
 		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
 	}
 	}

+ 46 - 0
integration-cli/docker_cli_network_unix_test.go

@@ -1110,6 +1110,52 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C)
 	dockerCmd(c, "network", "connect", "test1", "c1")
 	dockerCmd(c, "network", "connect", "test1", "c1")
 }
 }
 
 
+func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) {
+	chk := checker.Equals
+	if !mustBeEqual {
+		chk = checker.Not(checker.Equals)
+	}
+	currentMapping, _ := dockerCmd(c, "port", container, port)
+	c.Assert(currentMapping, chk, originalMapping)
+}
+
+func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) {
+	// Connect and disconnect a container with explicit and non-explicit
+	// host port mapping to/from networks which do cause and do not cause
+	// the container default gateway to change, and verify docker port cmd
+	// returns congruent information
+	testRequires(c, NotArm)
+	cnt := "c1"
+	dockerCmd(c, "network", "create", "aaa")
+	dockerCmd(c, "network", "create", "ccc")
+
+	dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top")
+	c.Assert(waitRun(cnt), check.IsNil)
+	curPortMap, _ := dockerCmd(c, "port", cnt, "70")
+	curExplPortMap, _ := dockerCmd(c, "port", cnt, "90")
+
+	// Connect to a network which causes the container's default gw switch
+	dockerCmd(c, "network", "connect", "aaa", cnt)
+	verifyPortMap(c, cnt, "70", curPortMap, false)
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
+
+	// Read current mapping
+	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
+
+	// Disconnect from a network which causes the container's default gw switch
+	dockerCmd(c, "network", "disconnect", "aaa", cnt)
+	verifyPortMap(c, cnt, "70", curPortMap, false)
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
+
+	// Read current mapping
+	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
+
+	// Connect to a network which does not cause the container's default gw switch
+	dockerCmd(c, "network", "connect", "ccc", cnt)
+	verifyPortMap(c, cnt, "70", curPortMap, true)
+	verifyPortMap(c, cnt, "90", curExplPortMap, true)
+}
+
 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
 	macAddress := "02:42:ac:11:00:02"
 	macAddress := "02:42:ac:11:00:02"
 	dockerCmd(c, "network", "create", "mynetwork")
 	dockerCmd(c, "network", "create", "mynetwork")