diff --git a/libnetwork/etchosts/etchosts.go b/libnetwork/etchosts/etchosts.go index 35845fe94aa0d..945451820af7f 100644 --- a/libnetwork/etchosts/etchosts.go +++ b/libnetwork/etchosts/etchosts.go @@ -143,6 +143,10 @@ func mergeRecords(path string, recs []Record) ([]byte, error) { } // Delete deletes an arbitrary number of Records already existing in /etc/hosts file +// +// FIXME(robmry) - this only matches on hostname, not address. So, if a container +// is connected to two networks then disconnected from one of them, the hosts +// entries for both networks are deleted. func Delete(path string, recs []Record) error { defer pathLock(path)() diff --git a/libnetwork/internal/resolvconf/resolvconf.go b/libnetwork/internal/resolvconf/resolvconf.go index 6621de64eb3ea..0973ff8fd477a 100644 --- a/libnetwork/internal/resolvconf/resolvconf.go +++ b/libnetwork/internal/resolvconf/resolvconf.go @@ -239,46 +239,30 @@ func (rc *ResolvConf) TransformForLegacyNw(ipv6 bool) { // - Add internalNS as a nameserver. // - Remove other nameservers, stashing them as ExtNameServers for the // internal resolver to use. -// - Mark ExtNameServers that must be used in the host namespace. +// - Mark ExtNameServers that must be accessed from the host namespace. // - If no ExtNameServer addresses are found, use the defaults. -// - Return an error if an "ndots" option inherited from the host's config, or -// supplied in an override is not valid. // - Ensure there's an 'options' value for each entry in reqdOptions. If the // option includes a ':', and an option with a matching prefix exists, it // is not modified. func (rc *ResolvConf) TransformForIntNS( - ipv6 bool, internalNS netip.Addr, reqdOptions []string, ) ([]ExtDNSEntry, error) { - // The transformed config must list the internal nameserver. - newNSs := []netip.Addr{internalNS} - // Filter out other nameservers, keeping them for use as upstream nameservers by the - // internal nameserver. + // Add each of the nameservers read from the host's /etc/hosts or supplied as an + // override to ExtNameServers, for the internal resolver to talk to. Addresses + // read from host config should be accessed from the host's network namespace + // (HostLoopback=true). Addresses supplied as overrides are accessed from the + // container's namespace. rc.md.ExtNameServers = nil for _, addr := range rc.nameServers { - // Extract this NS. Mark addresses that did not come from an override, but will - // definitely not work in the container's namespace as 'HostLoopback'. Upstream - // requests for these servers will be made in the host's network namespace. (So, - // '--dns 127.0.0.53' means use a nameserver listening on the container's - // loopback interface. But, if the host's resolv.conf contains 'nameserver - // 127.0.0.53', the host's resolver will be used.) rc.md.ExtNameServers = append(rc.md.ExtNameServers, ExtDNSEntry{ Addr: addr, - HostLoopback: !rc.md.NSOverride && (addr.IsLoopback() || (addr.Is6() && !ipv6) || addr.Zone() != ""), + HostLoopback: !rc.md.NSOverride, }) } - rc.nameServers = newNSs - // If there are no external nameservers, and the only nameserver left is the - // internal resolver, use the defaults as ext nameservers. - if len(rc.md.ExtNameServers) == 0 && len(rc.nameServers) == 1 { - log.G(context.TODO()).Info("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers") - for _, addr := range defaultNSAddrs(ipv6) { - rc.md.ExtNameServers = append(rc.md.ExtNameServers, ExtDNSEntry{Addr: addr}) - } - rc.md.UsedDefaultNS = true - } + // The transformed config only lists the internal nameserver. + rc.nameServers = []netip.Addr{internalNS} // For each option required by the nameserver, add it if not already present. If // the option is already present, don't override it. Apart from ndots - if the diff --git a/libnetwork/internal/resolvconf/resolvconf_test.go b/libnetwork/internal/resolvconf/resolvconf_test.go index fd843b10992e8..272cba2b2bcd0 100644 --- a/libnetwork/internal/resolvconf/resolvconf_test.go +++ b/libnetwork/internal/resolvconf/resolvconf_test.go @@ -340,7 +340,6 @@ func TestRCTransformForIntNS(t *testing.T) { name string input string intNameServer string - ipv6 bool overrideNS []string overrideOptions []string reqdOptions []string @@ -350,30 +349,19 @@ func TestRCTransformForIntNS(t *testing.T) { { name: "IPv4 only", input: "nameserver 10.0.0.1", - expExtServers: []ExtDNSEntry{mke("10.0.0.1", false)}, + expExtServers: []ExtDNSEntry{mke("10.0.0.1", true)}, }, { name: "IPv4 and IPv6, ipv6 enabled", input: "nameserver 10.0.0.1\nnameserver fdb6:b8fe:b528::1", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("10.0.0.1", false), - mke("fdb6:b8fe:b528::1", false), - }, - }, - { - name: "IPv4 and IPv6, ipv6 disabled", - input: "nameserver 10.0.0.1\nnameserver fdb6:b8fe:b528::1", - ipv6: false, expExtServers: []ExtDNSEntry{ - mke("10.0.0.1", false), + mke("10.0.0.1", true), mke("fdb6:b8fe:b528::1", true), }, }, { name: "IPv4 localhost", input: "nameserver 127.0.0.53", - ipv6: false, expExtServers: []ExtDNSEntry{mke("127.0.0.53", true)}, }, { @@ -381,78 +369,22 @@ func TestRCTransformForIntNS(t *testing.T) { // loopback interface, not the host's. name: "IPv4 localhost override", input: "nameserver 10.0.0.1", - ipv6: false, overrideNS: []string{"127.0.0.53"}, expExtServers: []ExtDNSEntry{mke("127.0.0.53", false)}, }, { - name: "IPv4 localhost, ipv6 enabled", - input: "nameserver 127.0.0.53", - ipv6: true, - expExtServers: []ExtDNSEntry{mke("127.0.0.53", true)}, - }, - { - name: "IPv6 addr, IPv6 enabled", + name: "IPv6 only", input: "nameserver fd14:6e0e:f855::1", - ipv6: true, - expExtServers: []ExtDNSEntry{mke("fd14:6e0e:f855::1", false)}, + expExtServers: []ExtDNSEntry{mke("fd14:6e0e:f855::1", true)}, }, { - name: "IPv4 and IPv6 localhost, IPv6 disabled", + name: "IPv4 and IPv6 localhost", input: "nameserver 127.0.0.53\nnameserver ::1", - ipv6: false, expExtServers: []ExtDNSEntry{ mke("127.0.0.53", true), mke("::1", true), }, }, - { - name: "IPv4 and IPv6 localhost, ipv6 enabled", - input: "nameserver 127.0.0.53\nnameserver ::1", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("127.0.0.53", true), - mke("::1", true), - }, - }, - { - name: "IPv4 localhost, IPv6 private, IPv6 enabled", - input: "nameserver 127.0.0.53\nnameserver fd3e:2d1a:1f5a::1", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("127.0.0.53", true), - mke("fd3e:2d1a:1f5a::1", false), - }, - }, - { - name: "IPv4 localhost, IPv6 private, IPv6 disabled", - input: "nameserver 127.0.0.53\nnameserver fd3e:2d1a:1f5a::1", - ipv6: false, - expExtServers: []ExtDNSEntry{ - mke("127.0.0.53", true), - mke("fd3e:2d1a:1f5a::1", true), - }, - }, - { - name: "No host nameserver, no iv6", - input: "", - ipv6: false, - expExtServers: []ExtDNSEntry{ - mke("8.8.8.8", false), - mke("8.8.4.4", false), - }, - }, - { - name: "No host nameserver, iv6", - input: "", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("8.8.8.8", false), - mke("8.8.4.4", false), - mke("2001:4860:4860::8888", false), - mke("2001:4860:4860::8844", false), - }, - }, { name: "ndots present and required", input: "nameserver 127.0.0.53\noptions ndots:1", @@ -496,7 +428,7 @@ func TestRCTransformForIntNS(t *testing.T) { rc.OverrideOptions(tc.overrideOptions) } intNS := netip.MustParseAddr(tc.intNameServer) - extNameServers, err := rc.TransformForIntNS(tc.ipv6, intNS, tc.reqdOptions) + extNameServers, err := rc.TransformForIntNS(intNS, tc.reqdOptions) if tc.expErr != "" { assert.Check(t, is.ErrorContains(err, tc.expErr)) return @@ -559,7 +491,7 @@ func TestRCTransformForIntNSInvalidNdots(t *testing.T) { content := "nameserver 8.8.8.8\n" + tc.options rc, err := Parse(bytes.NewBuffer([]byte(content)), "/etc/resolv.conf") assert.NilError(t, err) - _, err = rc.TransformForIntNS(false, netip.MustParseAddr("127.0.0.11"), tc.reqdOptions) + _, err = rc.TransformForIntNS(netip.MustParseAddr("127.0.0.11"), tc.reqdOptions) assert.NilError(t, err) val, found := rc.Option("ndots") diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden deleted file mode 100644 index 23dec24ad20f0..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [10.0.0.1 host(fdb6:b8fe:b528::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden index f1f5ea0bcaa33..04308659f30f7 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [10.0.0.1 fdb6:b8fe:b528::1] +# ExtServers: [host(10.0.0.1) host(fdb6:b8fe:b528::1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden deleted file mode 100644 index 387cc713b7b36..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) host(::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_IPv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost.golden similarity index 100% rename from libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_IPv6_disabled.golden rename to libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost.golden diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden deleted file mode 100644 index 2f58161ae67a9..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) host(fd3e:2d1a:1f5a::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden deleted file mode 100644 index 4d7ac5e73e94b..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) fd3e:2d1a:1f5a::1] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden index 4479c5936980c..58dadc47fb7e9 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [10.0.0.1] +# ExtServers: [host(10.0.0.1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden deleted file mode 100644 index 36cbb47099ee6..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [fd14:6e0e:f855::1] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_only.golden similarity index 71% rename from libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden rename to libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_only.golden index 926d44d49a12d..3dd9cf69e88fc 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_only.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53)] +# ExtServers: [host(fd14:6e0e:f855::1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden deleted file mode 100644 index cde7c90bd9852..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden +++ /dev/null @@ -1,6 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# Used default nameservers. -# ExtServers: [8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden deleted file mode 100644 index c620d3442d1e2..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden +++ /dev/null @@ -1,6 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# Used default nameservers. -# ExtServers: [8.8.8.8 8.8.4.4] -# Overrides: [] diff --git a/libnetwork/libnetwork_internal_test.go b/libnetwork/libnetwork_internal_test.go index cb60804fde9a8..523fa93245786 100644 --- a/libnetwork/libnetwork_internal_test.go +++ b/libnetwork/libnetwork_internal_test.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/internal/testutils/netnsutils" "github.com/docker/docker/libnetwork/config" "github.com/docker/docker/libnetwork/driverapi" + "github.com/docker/docker/libnetwork/etchosts" "github.com/docker/docker/libnetwork/ipams/defaultipam" "github.com/docker/docker/libnetwork/ipamutils" "github.com/docker/docker/libnetwork/netlabel" @@ -358,6 +359,91 @@ func TestAuxAddresses(t *testing.T) { } } +func TestUpdateSvcRecord(t *testing.T) { + skip.If(t, runtime.GOOS == "windows", "bridge driver and IPv6, only works on linux") + + tests := []struct { + name string + epName string + addr4 string + addr6 string + expSvcRecs []etchosts.Record + }{ + { + name: "v4only", + epName: "ep4", + addr4: "172.16.0.2/24", + expSvcRecs: []etchosts.Record{ + {Hosts: "id-ep4", IP: "172.16.0.2"}, + }, + }, + /* TODO(robmry) - add this test when the bridge driver understands v6-only + { + name: "v6only", + epName: "ep6", + addr6: "fde6:045d:b2aa::2/64", + expSvcRecs: []etchosts.Record{ + {Hosts: "id-ep6", IP: "fde6:45d:b2aa::2"}, + }, + }, + */ + { + name: "dual-stack", + epName: "ep46", + addr4: "172.16.1.2/24", + addr6: "fd60:8677:5a4c::2/64", + expSvcRecs: []etchosts.Record{ + {Hosts: "id-ep46", IP: "172.16.1.2"}, + {Hosts: "id-ep46", IP: "fd60:8677:5a4c::2"}, + }, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + defer netnsutils.SetupTestOSContext(t)() + ctrlr, err := New(OptionBoltdbWithRandomDBFile(t)) + assert.NilError(t, err) + defer ctrlr.Stop() + + var ipam4, ipam6 []*IpamConf + var ip4, ip6 net.IP + if tc.addr4 != "" { + var net4 *net.IPNet + ip4, net4, err = net.ParseCIDR(tc.addr4) + assert.NilError(t, err) + ipam4 = []*IpamConf{{PreferredPool: net4.String()}} + } + if tc.addr6 != "" { + var net6 *net.IPNet + ip6, net6, err = net.ParseCIDR(tc.addr6) + assert.NilError(t, err) + ipam6 = []*IpamConf{{PreferredPool: net6.String()}} + } + n, err := ctrlr.NewNetwork("bridge", "net1", "", nil, + NetworkOptionEnableIPv4(tc.addr4 != ""), + NetworkOptionEnableIPv6(tc.addr6 != ""), + NetworkOptionIpam(defaultipam.DriverName, "", ipam4, ipam6, nil), + ) + assert.NilError(t, err) + ep, err := n.CreateEndpoint(context.Background(), tc.epName, + CreateOptionDNSNames([]string{tc.epName, "id-" + tc.epName}), + CreateOptionIpam(ip4, ip6, nil, nil), + ) + assert.NilError(t, err) + + n.updateSvcRecord(context.Background(), ep, true) + recs := n.getSvcRecords(ep) + assert.Check(t, is.DeepEqual(recs, tc.expSvcRecs)) + + n.updateSvcRecord(context.Background(), ep, false) + recs = n.getSvcRecords(ep) + assert.Check(t, is.Nil(recs)) + }) + } +} + func TestSRVServiceQuery(t *testing.T) { skip.If(t, runtime.GOOS == "windows", "test only works on linux") diff --git a/libnetwork/network.go b/libnetwork/network.go index dc51eac48c8e3..40972f0aa9f03 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -1329,11 +1329,14 @@ func (n *Network) updateSvcRecord(ctx context.Context, ep *Endpoint, isAdd bool) defer span.End() iface := ep.Iface() - if iface == nil || iface.Address() == nil { + if iface == nil { return } - var ipv6 net.IP + var ipv4, ipv6 net.IP + if iface.Address() != nil { + ipv4 = iface.Address().IP + } if iface.AddressIPv6() != nil { ipv6 = iface.AddressIPv6().IP } @@ -1347,12 +1350,12 @@ func (n *Network) updateSvcRecord(ctx context.Context, ep *Endpoint, isAdd bool) if isAdd { for i, dnsName := range dnsNames { ipMapUpdate := i == 0 // ipMapUpdate indicates whether PTR records should be updated. - n.addSvcRecords(ep.ID(), dnsName, serviceID, iface.Address().IP, ipv6, ipMapUpdate, "updateSvcRecord") + n.addSvcRecords(ep.ID(), dnsName, serviceID, ipv4, ipv6, ipMapUpdate, "updateSvcRecord") } } else { for i, dnsName := range dnsNames { ipMapUpdate := i == 0 // ipMapUpdate indicates whether PTR records should be updated. - n.deleteSvcRecords(ep.ID(), dnsName, serviceID, iface.Address().IP, ipv6, ipMapUpdate, "updateSvcRecord") + n.deleteSvcRecords(ep.ID(), dnsName, serviceID, ipv4, ipv6, ipMapUpdate, "updateSvcRecord") } } } @@ -1392,14 +1395,14 @@ func delNameToIP(svcMap *setmatrix.SetMatrix[svcMapEntry], name, serviceID strin } // TODO(aker): remove ipMapUpdate param and add a proper method dedicated to update PTR records. -func (n *Network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP, ipMapUpdate bool, method string) { +func (n *Network) addSvcRecords(eID, name, serviceID string, epIPv4, epIPv6 net.IP, ipMapUpdate bool, method string) { // Do not add service names for ingress network as this is a // routing only network if n.ingress { return } networkID := n.ID() - log.G(context.TODO()).Debugf("%s (%.7s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, networkID, name, epIP, epIPv6, ipMapUpdate, method, serviceID) + log.G(context.TODO()).Debugf("%s (%.7s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, networkID, name, epIPv4, epIPv6, ipMapUpdate, method, serviceID) c := n.getController() c.mu.Lock() @@ -1412,26 +1415,30 @@ func (n *Network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP } if ipMapUpdate { - addIPToName(&sr.ipMap, name, serviceID, epIP) + if epIPv4 != nil { + addIPToName(&sr.ipMap, name, serviceID, epIPv4) + } if epIPv6 != nil { addIPToName(&sr.ipMap, name, serviceID, epIPv6) } } - addNameToIP(&sr.svcMap, name, serviceID, epIP) + if epIPv4 != nil { + addNameToIP(&sr.svcMap, name, serviceID, epIPv4) + } if epIPv6 != nil { addNameToIP(&sr.svcIPv6Map, name, serviceID, epIPv6) } } -func (n *Network) deleteSvcRecords(eID, name, serviceID string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool, method string) { +func (n *Network) deleteSvcRecords(eID, name, serviceID string, epIPv4, epIPv6 net.IP, ipMapUpdate bool, method string) { // Do not delete service names from ingress network as this is a // routing only network if n.ingress { return } networkID := n.ID() - log.G(context.TODO()).Debugf("%s (%.7s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, networkID, name, epIP, epIPv6, ipMapUpdate, method, serviceID) + log.G(context.TODO()).Debugf("%s (%.7s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, networkID, name, epIPv4, epIPv6, ipMapUpdate, method, serviceID) c := n.getController() c.mu.Lock() @@ -1443,15 +1450,17 @@ func (n *Network) deleteSvcRecords(eID, name, serviceID string, epIP net.IP, epI } if ipMapUpdate { - delIPToName(&sr.ipMap, name, serviceID, epIP) - + if epIPv4 != nil { + delIPToName(&sr.ipMap, name, serviceID, epIPv4) + } if epIPv6 != nil { delIPToName(&sr.ipMap, name, serviceID, epIPv6) } } - delNameToIP(&sr.svcMap, name, serviceID, epIP) - + if epIPv4 != nil { + delNameToIP(&sr.svcMap, name, serviceID, epIPv4) + } if epIPv6 != nil { delNameToIP(&sr.svcIPv6Map, name, serviceID, epIPv6) } @@ -1476,27 +1485,29 @@ func (n *Network) getSvcRecords(ep *Endpoint) []etchosts.Record { return nil } - svcMapKeys := sr.svcMap.Keys() - // Loop on service names on this network - for _, k := range svcMapKeys { - if strings.Split(k, ".")[0] == epName { - continue - } - // Get all the IPs associated to this service - mapEntryList, ok := sr.svcMap.Get(k) - if !ok { - // The key got deleted - continue - } - if len(mapEntryList) == 0 { - log.G(context.TODO()).Warnf("Found empty list of IP addresses for service %s on network %s (%s)", k, n.name, n.id) - continue - } + for _, svcMap := range []*setmatrix.SetMatrix[svcMapEntry]{&sr.svcMap, &sr.svcIPv6Map} { + svcMapKeys := svcMap.Keys() + // Loop on service names on this network + for _, k := range svcMapKeys { + if strings.Split(k, ".")[0] == epName { + continue + } + // Get all the IPs associated to this service + mapEntryList, ok := svcMap.Get(k) + if !ok { + // The key got deleted + continue + } + if len(mapEntryList) == 0 { + log.G(context.TODO()).Warnf("Found empty list of IP addresses for service %s on network %s (%s)", k, n.name, n.id) + continue + } - recs = append(recs, etchosts.Record{ - Hosts: k, - IP: mapEntryList[0].ip, - }) + recs = append(recs, etchosts.Record{ + Hosts: k, + IP: mapEntryList[0].ip, + }) + } } return recs diff --git a/libnetwork/sandbox_dns_unix.go b/libnetwork/sandbox_dns_unix.go index dc86ca645648b..ecf81e6d129f0 100644 --- a/libnetwork/sandbox_dns_unix.go +++ b/libnetwork/sandbox_dns_unix.go @@ -336,21 +336,6 @@ func (sb *Sandbox) rebuildDNS() error { return err } - // Check for IPv6 endpoints in this sandbox. If there are any, and the container has - // IPv6 enabled, upstream requests from the internal DNS resolver can be made from - // the container's namespace. - // TODO(robmry) - this can only check networks connected when the resolver is set up, - // the configuration won't be updated if the container gets an IPv6 address later. - ipv6 := false - for _, ep := range sb.endpoints { - if ep.network.enableIPv6 { - if en, ok := sb.ipv6Enabled(); ok { - ipv6 = en - } - break - } - } - intNS := sb.resolver.NameServer() if !intNS.IsValid() { return fmt.Errorf("no listen-address for internal resolver") @@ -360,7 +345,7 @@ func (sb *Sandbox) rebuildDNS() error { _, sb.ndotsSet = rc.Option("ndots") // Swap nameservers for the internal one, and make sure the required options are set. var extNameServers []resolvconf.ExtDNSEntry - extNameServers, err = rc.TransformForIntNS(ipv6, intNS, sb.resolver.ResolverOptions()) + extNameServers, err = rc.TransformForIntNS(intNS, sb.resolver.ResolverOptions()) if err != nil { return err }