Skip to content

Commit

Permalink
Merge pull request #17393 from tiborvass/carry-17360
Browse files Browse the repository at this point in the history
Carry Fix docker inspect container only reports last assigned information
  • Loading branch information
calavera committed Oct 28, 2015
2 parents 2266462 + 2568257 commit 9ab71b6
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 106 deletions.
26 changes: 23 additions & 3 deletions api/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/docker/docker/daemon/network"
"github.com/docker/docker/pkg/nat"
"github.com/docker/docker/pkg/version"
"github.com/docker/docker/registry"
"github.com/docker/docker/runconfig"
Expand Down Expand Up @@ -256,7 +257,6 @@ type ContainerJSONBase struct {
Args []string
State *ContainerState
Image string
NetworkSettings *network.Settings
ResolvConfPath string
HostnamePath string
HostsPath string
Expand All @@ -278,8 +278,28 @@ type ContainerJSONBase struct {
// ContainerJSON is newly used struct along with MountPoint
type ContainerJSON struct {
*ContainerJSONBase
Mounts []MountPoint
Config *runconfig.Config
Mounts []MountPoint
Config *runconfig.Config
NetworkSettings *NetworkSettings
}

// NetworkSettings exposes the network settings in the api
type NetworkSettings struct {
NetworkSettingsBase
Networks map[string]*network.EndpointSettings
}

// NetworkSettingsBase holds basic information about networks
type NetworkSettingsBase struct {
Bridge string
SandboxID string
HairpinMode bool
LinkLocalIPv6Address string
LinkLocalIPv6PrefixLen int
Ports nat.PortMap
SandboxKey string
SecondaryIPAddresses []network.Address
SecondaryIPv6Addresses []network.Address
}

// MountPoint represents a mount point configuration inside the container.
Expand Down
8 changes: 5 additions & 3 deletions api/types/versions/v1p19/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v1p19

import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions/v1p20"
"github.com/docker/docker/pkg/nat"
"github.com/docker/docker/runconfig"
)
Expand All @@ -11,9 +12,10 @@ import (
// Note this is not used by the Windows daemon.
type ContainerJSON struct {
*types.ContainerJSONBase
Volumes map[string]string
VolumesRW map[string]bool
Config *ContainerConfig
Volumes map[string]string
VolumesRW map[string]bool
Config *ContainerConfig
NetworkSettings *v1p20.NetworkSettings
}

// ContainerConfig is a backcompatibility struct for APIs prior to 1.20.
Expand Down
18 changes: 16 additions & 2 deletions api/types/versions/v1p20/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import (
// ContainerJSON is a backcompatibility struct for the API 1.20
type ContainerJSON struct {
*types.ContainerJSONBase
Mounts []types.MountPoint
Config *ContainerConfig
Mounts []types.MountPoint
Config *ContainerConfig
NetworkSettings *NetworkSettings
}

// ContainerConfig is a backcompatibility struct used in ContainerJSON for the API 1.20
Expand All @@ -31,3 +32,16 @@ type StatsJSON struct {
types.Stats
Network types.NetworkStats `json:"network,omitempty"`
}

// NetworkSettings is a backward compatible struct for APIs prior to 1.21
type NetworkSettings struct {
types.NetworkSettingsBase
EndpointID string
Gateway string
GlobalIPv6Address string
GlobalIPv6PrefixLen int
IPAddress string
IPPrefixLen int
IPv6Gateway string
MacAddress string
}
4 changes: 0 additions & 4 deletions daemon/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,6 @@ func (streamConfig *streamConfig) StderrPipe() io.ReadCloser {
return ioutils.NewBufReader(reader)
}

func (container *Container) isNetworkAllocated() bool {
return container.NetworkSettings.IPAddress != ""
}

// cleanup releases any network resources allocated to the container along with any rules
// around how containers are linked together. It also unmounts the container's root filesystem.
func (container *Container) cleanup() {
Expand Down
106 changes: 58 additions & 48 deletions daemon/container_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,25 @@ func (container *Container) setupLinkedContainers() ([]string, error) {
return nil, err
}

bridgeSettings := container.NetworkSettings.Networks["bridge"]
if bridgeSettings == nil {
return nil, nil
}

if len(children) > 0 {
for linkAlias, child := range children {
if !child.IsRunning() {
return nil, derr.ErrorCodeLinkNotRunning.WithArgs(child.Name, linkAlias)
}

childBridgeSettings := child.NetworkSettings.Networks["bridge"]
if childBridgeSettings == nil {
return nil, fmt.Errorf("container %d not attached to default bridge network", child.ID)
}

link := links.NewLink(
container.NetworkSettings.IPAddress,
child.NetworkSettings.IPAddress,
bridgeSettings.IPAddress,
childBridgeSettings.IPAddress,
linkAlias,
child.Config.Env,
child.Config.ExposedPorts,
Expand Down Expand Up @@ -542,13 +552,14 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
if alias != child.Name[1:] {
aliasList = aliasList + " " + child.Name[1:]
}
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.IPAddress))
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks["bridge"].IPAddress))
cEndpoint, _ := child.getEndpointInNetwork(n)
if cEndpoint != nil && cEndpoint.ID() != "" {
childEndpoints = append(childEndpoints, cEndpoint.ID())
}
}

bridgeSettings := container.NetworkSettings.Networks["bridge"]
refs := container.daemon.containerGraph().RefPaths(container.ID)
for _, ref := range refs {
if ref.ParentID == "0" {
Expand All @@ -561,8 +572,8 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
}

if c != nil && !container.daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, container.NetworkSettings.IPAddress))
logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, bridgeSettings.IPAddress)
sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, bridgeSettings.IPAddress))
if ep.ID() != "" {
parentEndpoints = append(parentEndpoints, ep.ID())
}
Expand All @@ -583,12 +594,8 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw

func isLinkable(child *Container) bool {
// A container is linkable only if it belongs to the default network
for _, nw := range child.NetworkSettings.Networks {
if nw == "bridge" {
return true
}
}
return false
_, ok := child.NetworkSettings.Networks["bridge"]
return ok
}

func (container *Container) getEndpointInNetwork(n libnetwork.Network) (libnetwork.Endpoint, error) {
Expand All @@ -615,10 +622,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 {
Expand Down Expand Up @@ -652,7 +655,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
}
Expand All @@ -667,48 +670,64 @@ func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSet
return networkSettings, nil
}

if _, ok := networkSettings.Networks[n.Name()]; !ok {
networkSettings.Networks[n.Name()] = new(network.EndpointSettings)
}
networkSettings.Networks[n.Name()].EndpointID = ep.ID()

iface := epInfo.Iface()
if iface == nil {
return networkSettings, nil
}

if iface.Address() != nil {
ones, _ := iface.Address().Mask.Size()
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
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 {
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()
container.NetworkSettings.Networks[n.Name()].Gateway = epInfo.Gateway().String()
if epInfo.GatewayIPv6().To16() != nil {
container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
container.NetworkSettings.Networks[n.Name()].IPv6Gateway = epInfo.GatewayIPv6().String()
}

return nil
}

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
Expand All @@ -727,7 +746,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
}
Expand All @@ -738,7 +757,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
}
Expand Down Expand Up @@ -769,7 +788,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
Expand Down Expand Up @@ -899,9 +918,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() {
Expand All @@ -912,11 +930,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
}
Expand Down Expand Up @@ -1015,7 +1034,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)
}

Expand Down Expand Up @@ -1142,6 +1161,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}

Expand Down Expand Up @@ -1199,19 +1221,7 @@ 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
}
}

delete(container.NetworkSettings.Networks, n.Name())
return nil
}

Expand Down

0 comments on commit 9ab71b6

Please sign in to comment.