diff --git a/endpoint.go b/endpoint.go index f0af1e7538..2456a46abf 100644 --- a/endpoint.go +++ b/endpoint.go @@ -391,6 +391,14 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error { } }() + if len(ep.iface.dnsServers) > 0 || len(ep.iface.dnsSearchDomains) > 0 { + sb.config.dnsList = appendUnique(sb.config.dnsList, ep.iface.dnsServers) + sb.config.dnsSearchList = appendUnique(sb.config.dnsSearchList, ep.iface.dnsSearchDomains) + if err = sb.setupResolutionFiles(); err != nil { + log.Errorf("Error in setting up resolution files: err %+v", err) + } + } + nid := n.ID() ep.processOptions(options...) @@ -472,6 +480,18 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error { return sb.clearDefaultGW() } +func appendUnique(list1, list2 []string) []string { + encountered := map[string]bool{} + var result []string + for _, el := range append(list1, list2...) { + if !encountered[el] { + encountered[el] = true + result = append(result, el) + } + } + return result +} + func (ep *endpoint) rename(name string) error { var err error n := ep.getNetwork() @@ -887,13 +907,17 @@ func (ep *endpoint) assignAddress(ipam ipamapi.Ipam, assignIPv4, assignIPv6 bool func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error { var ( - poolID *string - address **net.IPNet - prefAdd net.IP - progAdd net.IP + poolID *string + address **net.IPNet + dnsServers *[]string + dnsSearchDomains *[]string + prefAdd net.IP + progAdd net.IP ) n := ep.getNetwork() + dnsServers = &ep.iface.dnsServers + dnsSearchDomains = &ep.iface.dnsSearchDomains switch ipVer { case 4: poolID = &ep.iface.v4PoolID @@ -926,10 +950,16 @@ func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error { if progAdd != nil && !d.Pool.Contains(progAdd) { continue } - addr, _, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions) + addr, ipamData, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions) if err == nil { ep.Lock() *address = addr + if len(ipamData["DNSServers"]) > 0 { + *dnsServers = strings.Split(ipamData["DNSServers"], " ") + } + if len(ipamData["DNSSearchDomains"]) > 0 { + *dnsSearchDomains = strings.Split(ipamData["DNSSearchDomains"], " ") + } *poolID = d.PoolID ep.Unlock() return nil diff --git a/endpoint_info.go b/endpoint_info.go index 4ba8e3d548..64c6beee3d 100644 --- a/endpoint_info.go +++ b/endpoint_info.go @@ -46,14 +46,16 @@ type InterfaceInfo interface { } type endpointInterface struct { - mac net.HardwareAddr - addr *net.IPNet - addrv6 *net.IPNet - srcName string - dstPrefix string - routes []*net.IPNet - v4PoolID string - v6PoolID string + mac net.HardwareAddr + addr *net.IPNet + addrv6 *net.IPNet + dnsServers []string + dnsSearchDomains []string + srcName string + dstPrefix string + routes []*net.IPNet + v4PoolID string + v6PoolID string } func (epi *endpointInterface) MarshalJSON() ([]byte, error) { @@ -67,6 +69,8 @@ func (epi *endpointInterface) MarshalJSON() ([]byte, error) { if epi.addrv6 != nil { epMap["addrv6"] = epi.addrv6.String() } + epMap["dnsServers"] = epi.dnsServers + epMap["dnsSearchDomains"] = epi.dnsSearchDomains epMap["srcName"] = epi.srcName epMap["dstPrefix"] = epi.dstPrefix var routes []string @@ -103,6 +107,16 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) error { } } + ds, _ := json.Marshal(epMap["dnsServers"]) + var dnsServers []string + json.Unmarshal(ds, &dnsServers) + epi.dnsServers = dnsServers + + dsl, _ := json.Marshal(epMap["dnsSearchDomains"]) + var dnsSearchDomains []string + json.Unmarshal(dsl, &dnsSearchDomains) + epi.dnsSearchDomains = dnsSearchDomains + epi.srcName = epMap["srcName"].(string) epi.dstPrefix = epMap["dstPrefix"].(string) @@ -127,6 +141,15 @@ func (epi *endpointInterface) CopyTo(dstEpi *endpointInterface) error { dstEpi.mac = types.GetMacCopy(epi.mac) dstEpi.addr = types.GetIPNetCopy(epi.addr) dstEpi.addrv6 = types.GetIPNetCopy(epi.addrv6) + + dstEpi.dnsServers = make([]string, len(epi.dnsServers)) + copy(dstEpi.dnsServers, epi.dnsServers) + dstEpi.dnsServers = epi.dnsServers + + dstEpi.dnsSearchDomains = make([]string, len(epi.dnsSearchDomains)) + copy(dstEpi.dnsSearchDomains, epi.dnsSearchDomains) + dstEpi.dnsSearchDomains = epi.dnsSearchDomains + dstEpi.srcName = epi.srcName dstEpi.dstPrefix = epi.dstPrefix dstEpi.v4PoolID = epi.v4PoolID diff --git a/ipams/remote/remote_test.go b/ipams/remote/remote_test.go index 3c6cc4bfa9..f4b0790138 100644 --- a/ipams/remote/remote_test.go +++ b/ipams/remote/remote_test.go @@ -9,6 +9,7 @@ import ( "net/http" "net/http/httptest" "os" + "strings" "testing" "github.com/docker/docker/pkg/plugins" @@ -197,8 +198,13 @@ func TestRemoteDriver(t *testing.T) { ip = "172.20.0.34" } ip = fmt.Sprintf("%s/16", ip) + dnsList := []string{"172.20.0.1", "172.20.0.2"} + dnsSearchList := []string{"domain1", "domain2"} + ipamData := map[string]string{"DNSServers": strings.Join(dnsList, " "), + "DNSSearchDomains": strings.Join(dnsSearchList, " ")} return map[string]interface{}{ "Address": ip, + "Data": ipamData, } }) @@ -267,7 +273,7 @@ func TestRemoteDriver(t *testing.T) { } // Request any address - addr, _, err := d.RequestAddress(poolID2, nil, nil) + addr, ipamData, err := d.RequestAddress(poolID2, nil, nil) if err != nil { t.Fatal(err) } @@ -275,6 +281,29 @@ func TestRemoteDriver(t *testing.T) { t.Fatalf("Unexpected address: %s", addr) } + dnsList := strings.Split(ipamData["DNSServers"], " ") + dnsSearchDomains := strings.Split(ipamData["DNSSearchDomains"], " ") + + expectedDNSList := []string{"172.20.0.1", "172.20.0.2"} + if dnsList == nil || len(dnsList) != len(expectedDNSList) { + t.Fatalf("Unexpected DNS list: %+v", dnsList) + } + for i, exp := range expectedDNSList { + if dnsList[i] != exp { + t.Fatalf("Expected DNS IP: %s, got %s", exp, dnsList[i]) + } + } + + expectedDNSSearchDomains := []string{"domain1", "domain2"} + if dnsSearchDomains == nil || len(dnsSearchDomains) != len(expectedDNSSearchDomains) { + t.Fatalf("Unexpected DNS Search Domains: %+v", dnsSearchDomains) + } + for i, exp := range expectedDNSSearchDomains { + if dnsSearchDomains[i] != exp { + t.Fatalf("Expected DNS Search domain: %s, got %s", exp, dnsSearchDomains[i]) + } + } + // Request specific address addr2, _, err := d.RequestAddress(poolID2, net.ParseIP("172.20.1.45"), nil) if err != nil {