diff --git a/daemon/container_unix.go b/daemon/container_unix.go index fb6695cc3e..c005347f14 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -680,6 +680,10 @@ func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwor return networkSettings, nil } + if iface.MacAddress() != nil { + networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() + } + if iface.Address() != nil { ones, _ := iface.Address().Mask.Size() networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() @@ -692,23 +696,14 @@ func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwor 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(n libnetwork.Network, ep libnetwork.Endpoint) error { + if _, err := container.buildPortMapInfo(ep, container.NetworkSettings); err != nil { + return err + } + epInfo := ep.Info() if epInfo == nil { // It is not an error to get an empty endpoint info @@ -754,12 +749,7 @@ func (container *Container) updateNetworkSettings(n libnetwork.Network) error { } func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error { - networkSettings, err := container.buildPortMapInfo(ep, container.NetworkSettings) - if err != nil { - return err - } - - networkSettings, err = container.buildEndpointInfo(n, ep, networkSettings) + networkSettings, err := container.buildEndpointInfo(n, ep, container.NetworkSettings) if err != nil { return err } diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index d4a7eb337f..432c40abda 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -20,6 +20,7 @@ import ( remoteipam "github.com/docker/libnetwork/ipams/remote/api" "github.com/docker/libnetwork/netlabel" "github.com/go-check/check" + "github.com/vishvananda/netlink" ) const dummyNetworkDriver = "dummy-network-driver" @@ -79,6 +80,36 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) { fmt.Fprintf(w, "null") }) + mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + fmt.Fprintf(w, `{"Interface":{"MacAddress":"a0:b1:c2:d3:e4:f5"}}`) + }) + + mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + + veth := &netlink.Veth{ + LinkAttrs: netlink.LinkAttrs{Name: "randomIfName", TxQLen: 0}, PeerName: "cnt0"} + if err := netlink.LinkAdd(veth); err != nil { + fmt.Fprintf(w, `{"Error":"failed to add veth pair: `+err.Error()+`"}`) + } else { + fmt.Fprintf(w, `{"InterfaceName":{ "SrcName":"cnt0", "DstPrefix":"veth"}}`) + } + }) + + mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + fmt.Fprintf(w, "null") + }) + + mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + if link, err := netlink.LinkByName("cnt0"); err == nil { + netlink.LinkDel(link) + } + fmt.Fprintf(w, "null") + }) + // Ipam Driver implementation var ( poolRequest remoteipam.RequestPoolRequest @@ -566,3 +597,44 @@ func (s *DockerNetworkSuite) TestDockerNetworkLinkOndefaultNetworkOnly(c *check. dockerCmd(c, "network", "connect", "bridge", cnt2) dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top") } + +func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) { + // Verify exposed ports are present in ps output when running a container on + // a network managed by a driver which does not provide the default gateway + // for the container + nwn := "ov" + ctn := "bb" + port1 := 80 + port2 := 443 + expose1 := fmt.Sprintf("--expose=%d", port1) + expose2 := fmt.Sprintf("--expose=%d", port2) + + dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn) + assertNwIsAvailable(c, nwn) + + dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, expose1, expose2, "busybox", "top") + + // Check docker ps o/p for last created container reports the unpublished ports + unpPort1 := fmt.Sprintf("%d/tcp", port1) + unpPort2 := fmt.Sprintf("%d/tcp", port2) + out, _ := dockerCmd(c, "ps", "-n=1") + // Missing unpublished ports in docker ps output + c.Assert(out, checker.Contains, unpPort1) + // Missing unpublished ports in docker ps output + c.Assert(out, checker.Contains, unpPort2) +} + +func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) { + // Verify endpoint MAC address is correctly populated in container's network settings + nwn := "ov" + ctn := "bb" + + dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn) + assertNwIsAvailable(c, nwn) + + dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, "busybox", "top") + + mac, err := inspectField(ctn, "NetworkSettings.Networks."+nwn+".MacAddress") + c.Assert(err, checker.IsNil) + c.Assert(mac, checker.Equals, "a0:b1:c2:d3:e4:f5") +}