From a8dc0ba83a4da515d4a2b22a890fe8cdfa168b3d Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Wed, 25 May 2016 13:47:38 -0700 Subject: [PATCH] Update port info on network connect/disconnect Signed-off-by: Alessandro Boch (cherry picked from commit f198dfd856ca6125ef50b11d9d698550d66c9d4e) --- container/container.go | 5 +- daemon/container_operations.go | 5 ++ .../docker_cli_network_unix_test.go | 46 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/container/container.go b/container/container.go index ebafde7a0a..8781b796af 100644 --- a/container/container.go +++ b/container/container.go @@ -667,7 +667,8 @@ func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) { 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{} if sb == nil { return pm @@ -824,7 +825,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC } // 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 { return createOptions, nil } diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 310f9bb497..461439a6ce 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -26,6 +26,7 @@ var ( // ErrRootFSReadOnly is returned when a container // rootfs is marked readonly. 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) { @@ -581,6 +582,8 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName return fmt.Errorf("Updating join info failed: %v", err) } + container.NetworkSettings.Ports = getPortMapInfo(sb) + daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) return nil } @@ -633,6 +636,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) } + container.NetworkSettings.Ports = getPortMapInfo(sbox) + 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) } diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index 2ee2092c69..902766d0f7 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -1080,6 +1080,52 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C) 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) { macAddress := "02:42:ac:11:00:02" dockerCmd(c, "network", "create", "mynetwork")