Fix docker inspect container only reports last assigned information

Signed-off-by: Lei Jitang <leijitang@huawei.com>
This commit is contained in:
Lei Jitang 2015-10-26 08:00:49 -04:00 committed by Tibor Vass
parent bf9f2691ca
commit 1b9a08e719
6 changed files with 95 additions and 52 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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