diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index a5263d4051..8debc99ece 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -499,7 +499,10 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) { if doUpdateHostsFile(n, sb) { var addresses []string - if ip := ep.getFirstInterfaceAddress(); ip != nil { + if ip := ep.getFirstInterfaceIPv4Address(); ip != nil { + addresses = append(addresses, ip.String()) + } + if ip := ep.getFirstInterfaceIPv6Address(); ip != nil { addresses = append(addresses, ip.String()) } if err = sb.updateHostsFile(addresses); err != nil { @@ -912,7 +915,7 @@ func (ep *endpoint) getSandbox() (*sandbox, bool) { return ps, ok } -func (ep *endpoint) getFirstInterfaceAddress() net.IP { +func (ep *endpoint) getFirstInterfaceIPv4Address() net.IP { ep.Lock() defer ep.Unlock() @@ -923,6 +926,17 @@ func (ep *endpoint) getFirstInterfaceAddress() net.IP { return nil } +func (ep *endpoint) getFirstInterfaceIPv6Address() net.IP { + ep.Lock() + defer ep.Unlock() + + if ep.iface.addrv6 != nil { + return ep.iface.addrv6.IP + } + + return nil +} + // EndpointOptionGeneric function returns an option setter for a Generic option defined // in a Dictionary of Key-Value pair func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption { diff --git a/libnetwork/endpoint_test.go b/libnetwork/endpoint_test.go new file mode 100644 index 0000000000..675c7a8c17 --- /dev/null +++ b/libnetwork/endpoint_test.go @@ -0,0 +1,76 @@ +// +build !windows + +package libnetwork + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/docker/libnetwork/ipamapi" + "github.com/docker/libnetwork/osl" + "github.com/docker/libnetwork/testutils" +) + +func TestHostsEntries(t *testing.T) { + if !testutils.IsRunningInContainer() { + defer testutils.SetupTestOSContext(t)() + } + + expectedHostsFile := `127.0.0.1 localhost +::1 localhost ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +192.168.222.2 somehost.example.com somehost +fe90::2 somehost.example.com somehost +` + + opts := []NetworkOption{NetworkOptionEnableIPv6(true), NetworkOptionIpam(ipamapi.DefaultIPAM, "", + []*IpamConf{{PreferredPool: "192.168.222.0/24", Gateway: "192.168.222.1"}}, + []*IpamConf{{PreferredPool: "fe90::/64", Gateway: "fe90::1"}}, + nil)} + + c, nws := getTestEnv(t, opts) + ctrlr := c.(*controller) + + hostsFile, err := ioutil.TempFile("", "") + if err != nil { + t.Fatal(err) + } + defer os.Remove(hostsFile.Name()) + + sbx, err := ctrlr.NewSandbox("sandbox1", OptionHostsPath(hostsFile.Name()), OptionHostname("somehost.example.com")) + if err != nil { + t.Fatal(err) + } + + ep1, err := nws[0].CreateEndpoint("ep1") + if err != nil { + t.Fatal(err) + } + + if err := ep1.Join(sbx, JoinOptionPriority(ep1, 1)); err != nil { + t.Fatal(err) + } + + data, err := ioutil.ReadFile(hostsFile.Name()) + if err != nil { + t.Fatal(err) + } + + if string(data) != expectedHostsFile { + t.Fatalf("expected the hosts file to read:\n%q\nbut instead got the following:\n%q\n", expectedHostsFile, string(data)) + } + + if err := sbx.Delete(); err != nil { + t.Fatal(err) + } + + if len(ctrlr.sandboxes) != 0 { + t.Fatalf("controller sandboxes is not empty. len = %d", len(ctrlr.sandboxes)) + } + + osl.GC() +}