Selaa lähdekoodia

Fix docker inspect container only reports last assigned information

Signed-off-by: Lei Jitang <leijitang@huawei.com>
Lei Jitang 9 vuotta sitten
vanhempi
commit
1b9a08e719

+ 67 - 36
daemon/container_unix.go

@@ -615,10 +615,6 @@ func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint, networkSett
 		return networkSettings, nil
 	}
 
-	if mac, ok := driverInfo[netlabel.MacAddress]; ok {
-		networkSettings.MacAddress = mac.(net.HardwareAddr).String()
-	}
-
 	networkSettings.Ports = nat.PortMap{}
 
 	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
@@ -652,7 +648,7 @@ func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint, networkSett
 	return networkSettings, nil
 }
 
-func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
+func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
 	if ep == nil {
 		return nil, derr.ErrorCodeEmptyEndpoint
 	}
@@ -667,36 +663,70 @@ func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSet
 		return networkSettings, nil
 	}
 
+	networkSettings.Networks[n.Name()].EndpointID = ep.ID()
+
 	iface := epInfo.Iface()
 	if iface == nil {
 		return networkSettings, nil
 	}
 
+	if networkSettings.EndpointID == "" {
+		networkSettings.EndpointID = ep.ID()
+	}
 	if iface.Address() != nil {
 		ones, _ := iface.Address().Mask.Size()
-		networkSettings.IPAddress = iface.Address().IP.String()
-		networkSettings.IPPrefixLen = ones
+		if networkSettings.IPAddress == "" || networkSettings.IPPrefixLen == 0 {
+			networkSettings.IPAddress = iface.Address().IP.String()
+			networkSettings.IPPrefixLen = ones
+		}
+		networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String()
+		networkSettings.Networks[n.Name()].IPPrefixLen = ones
 	}
 
 	if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil {
 		onesv6, _ := iface.AddressIPv6().Mask.Size()
-		networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
-		networkSettings.GlobalIPv6PrefixLen = onesv6
+		if networkSettings.GlobalIPv6Address == "" || networkSettings.GlobalIPv6PrefixLen == 0 {
+			networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
+			networkSettings.GlobalIPv6PrefixLen = onesv6
+		}
+		networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String()
+		networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6
+	}
+
+	driverInfo, err := ep.DriverInfo()
+	if err != nil {
+		return nil, err
+	}
+
+	if driverInfo == nil {
+		// It is not an error for epInfo to be nil
+		return networkSettings, nil
+	}
+	if mac, ok := driverInfo[netlabel.MacAddress]; ok {
+		if networkSettings.MacAddress == "" {
+			networkSettings.MacAddress = mac.(net.HardwareAddr).String()
+		}
+		networkSettings.Networks[n.Name()].MacAddress = mac.(net.HardwareAddr).String()
 	}
 
 	return networkSettings, nil
 }
 
-func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
+func (container *Container) updateJoinInfo(n libnetwork.Network, ep libnetwork.Endpoint) error {
 	epInfo := ep.Info()
 	if epInfo == nil {
 		// It is not an error to get an empty endpoint info
 		return nil
 	}
-
-	container.NetworkSettings.Gateway = epInfo.Gateway().String()
+	if container.NetworkSettings.Gateway == "" {
+		container.NetworkSettings.Gateway = epInfo.Gateway().String()
+	}
+	container.NetworkSettings.Networks[n.Name()].Gateway = epInfo.Gateway().String()
 	if epInfo.GatewayIPv6().To16() != nil {
-		container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
+		if container.NetworkSettings.IPv6Gateway == "" {
+			container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
+		}
+		container.NetworkSettings.Networks[n.Name()].IPv6Gateway = epInfo.GatewayIPv6().String()
 	}
 
 	return nil
@@ -704,11 +734,10 @@ func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
 
 func (container *Container) updateNetworkSettings(n libnetwork.Network) error {
 	if container.NetworkSettings == nil {
-		container.NetworkSettings = &network.Settings{Networks: []string{}}
+		container.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)}
 	}
-	settings := container.NetworkSettings
 
-	for _, s := range settings.Networks {
+	for s := range container.NetworkSettings.Networks {
 		sn, err := container.daemon.FindNetwork(s)
 		if err != nil {
 			continue
@@ -727,7 +756,7 @@ func (container *Container) updateNetworkSettings(n libnetwork.Network) error {
 			return runconfig.ErrConflictNoNetwork
 		}
 	}
-	settings.Networks = append(settings.Networks, n.Name())
+	container.NetworkSettings.Networks[n.Name()] = new(network.EndpointSettings)
 
 	return nil
 }
@@ -738,7 +767,7 @@ func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network,
 		return err
 	}
 
-	networkSettings, err = container.buildEndpointInfo(ep, networkSettings)
+	networkSettings, err = container.buildEndpointInfo(n, ep, networkSettings)
 	if err != nil {
 		return err
 	}
@@ -769,7 +798,7 @@ func (container *Container) updateNetwork() error {
 
 	// Find if container is connected to the default bridge network
 	var n libnetwork.Network
-	for _, name := range container.NetworkSettings.Networks {
+	for name := range container.NetworkSettings.Networks {
 		sn, err := container.daemon.FindNetwork(name)
 		if err != nil {
 			continue
@@ -899,9 +928,8 @@ func createNetwork(controller libnetwork.NetworkController, dnet string, driver
 }
 
 func (container *Container) allocateNetwork() error {
-	settings := container.NetworkSettings.Networks
 	updateSettings := false
-	if settings == nil {
+	if len(container.NetworkSettings.Networks) == 0 {
 		mode := container.hostConfig.NetworkMode
 		controller := container.daemon.netController
 		if container.Config.NetworkDisabled || mode.IsContainer() {
@@ -912,11 +940,12 @@ func (container *Container) allocateNetwork() error {
 		if mode.IsDefault() {
 			networkName = controller.Config().Daemon.DefaultNetwork
 		}
-		settings = []string{networkName}
+		container.NetworkSettings.Networks = make(map[string]*network.EndpointSettings)
+		container.NetworkSettings.Networks[networkName] = new(network.EndpointSettings)
 		updateSettings = true
 	}
 
-	for _, n := range settings {
+	for n := range container.NetworkSettings.Networks {
 		if err := container.connectToNetwork(n, updateSettings); err != nil {
 			return err
 		}
@@ -1015,7 +1044,7 @@ func (container *Container) connectToNetwork(idOrName string, updateSettings boo
 		return err
 	}
 
-	if err := container.updateJoinInfo(ep); err != nil {
+	if err := container.updateJoinInfo(n, ep); err != nil {
 		return derr.ErrorCodeJoinInfo.WithArgs(err)
 	}
 
@@ -1142,6 +1171,9 @@ func (container *Container) releaseNetwork() {
 
 	sid := container.NetworkSettings.SandboxID
 	networks := container.NetworkSettings.Networks
+	for n := range networks {
+		networks[n] = &network.EndpointSettings{}
+	}
 
 	container.NetworkSettings = &network.Settings{Networks: networks}
 
@@ -1199,19 +1231,18 @@ func (container *Container) disconnectFromNetwork(n libnetwork.Network) error {
 		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
 	}
 
-	networks := container.NetworkSettings.Networks
-	for i, s := range networks {
-		sn, err := container.daemon.FindNetwork(s)
-		if err != nil {
-			continue
-		}
-		if sn.Name() == n.Name() {
-			networks = append(networks[:i], networks[i+1:]...)
-			container.NetworkSettings.Networks = networks
-			break
-		}
-	}
+	if container.NetworkSettings.EndpointID == container.NetworkSettings.Networks[n.Name()].EndpointID {
+		container.NetworkSettings.EndpointID = ""
+		container.NetworkSettings.Gateway = ""
+		container.NetworkSettings.GlobalIPv6Address = ""
+		container.NetworkSettings.GlobalIPv6PrefixLen = 0
+		container.NetworkSettings.IPAddress = ""
+		container.NetworkSettings.IPPrefixLen = 0
+		container.NetworkSettings.IPv6Gateway = ""
+		container.NetworkSettings.MacAddress = ""
 
+	}
+	delete(container.NetworkSettings.Networks, n.Name())
 	return nil
 }
 

+ 21 - 9
daemon/network/settings.go

@@ -26,22 +26,34 @@ type IPAMConfig struct {
 // TODO Windows. Many of these fields can be factored out.,
 type Settings struct {
 	Bridge                 string
-	EndpointID             string
+	EndpointID             string // this is for backward compatibility
 	SandboxID              string
-	Gateway                string
-	GlobalIPv6Address      string
-	GlobalIPv6PrefixLen    int
+	Gateway                string // this is for backward compatibility
+	GlobalIPv6Address      string // this is for backward compatibility
+	GlobalIPv6PrefixLen    int    // this is for backward compatibility
 	HairpinMode            bool
-	IPAddress              string
-	IPPrefixLen            int
-	IPv6Gateway            string
+	IPAddress              string // this is for backward compatibility
+	IPPrefixLen            int    // this is for backward compatibility
+	IPv6Gateway            string // this is for backward compatibility
 	LinkLocalIPv6Address   string
 	LinkLocalIPv6PrefixLen int
-	MacAddress             string
-	Networks               []string
+	MacAddress             string // this is for backward compatibility
+	Networks               map[string]*EndpointSettings
 	Ports                  nat.PortMap
 	SandboxKey             string
 	SecondaryIPAddresses   []Address
 	SecondaryIPv6Addresses []Address
 	IsAnonymousEndpoint    bool
 }
+
+// EndpointSettings stores the network endpoint details
+type EndpointSettings struct {
+	EndpointID          string
+	Gateway             string
+	IPAddress           string
+	IPPrefixLen         int
+	IPv6Gateway         string
+	GlobalIPv6Address   string
+	GlobalIPv6PrefixLen int
+	MacAddress          string
+}

+ 2 - 2
integration-cli/docker_api_network_test.go

@@ -54,7 +54,7 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
 	// run a container and attach it to the default bridge network
 	out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
 	containerID := strings.TrimSpace(out)
-	containerIP := findContainerIP(c, "test")
+	containerIP := findContainerIP(c, "test", "bridge")
 
 	// inspect default bridge network again and make sure the container is connected
 	nr = getNetworkResource(c, nr.ID)
@@ -122,7 +122,7 @@ func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
 	// check if container IP matches network inspect
 	ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
 	c.Assert(err, checker.IsNil)
-	containerIP := findContainerIP(c, "test")
+	containerIP := findContainerIP(c, "test", "testnetwork")
 	c.Assert(ip.String(), checker.Equals, containerIP)
 
 	// disconnect container from the network

+ 1 - 1
integration-cli/docker_api_stats_test.go

@@ -85,7 +85,7 @@ func (s *DockerSuite) TestApiStatsNetworkStats(c *check.C) {
 	c.Assert(waitRun(id), checker.IsNil)
 
 	// Retrieve the container address
-	contIP := findContainerIP(c, id)
+	contIP := findContainerIP(c, id, "bridge")
 	numPings := 10
 
 	var preRxPackets uint64

+ 1 - 1
integration-cli/docker_cli_network_unix_test.go

@@ -284,7 +284,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
 	// check if container IP matches network inspect
 	ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
 	c.Assert(err, check.IsNil)
-	containerIP := findContainerIP(c, "test")
+	containerIP := findContainerIP(c, "test", "test")
 	c.Assert(ip.String(), checker.Equals, containerIP)
 
 	// disconnect container from the network

+ 3 - 3
integration-cli/docker_utils.go

@@ -782,13 +782,13 @@ func dockerCmdInDirWithTimeout(timeout time.Duration, path string, args ...strin
 	return integration.DockerCmdInDirWithTimeout(dockerBinary, timeout, path, args...)
 }
 
-func findContainerIP(c *check.C, id string, vargs ...string) string {
-	out, _ := dockerCmd(c, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
+func findContainerIP(c *check.C, id string, network string) string {
+	out, _ := dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.IPAddress }}'", network), id)
 	return strings.Trim(out, " \r\n'")
 }
 
 func (d *Daemon) findContainerIP(id string) string {
-	return findContainerIP(d.c, id, "--host", d.sock())
+	return findContainerIP(d.c, id, "--host")
 }
 
 func getContainerCount() (int, error) {