From 1eb0751803530155491cd88353de6d8a4fd1e668 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Sat, 4 Nov 2023 12:22:40 +0100 Subject: [PATCH 01/10] daemon: endpoints on default nw aren't anonymous They just happen to exist on a network that doesn't support DNS-based service discovery (ie. no embedded DNS servers are started for them). Signed-off-by: Albin Kerouanton --- daemon/network.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/daemon/network.go b/daemon/network.go index d3e49e8b3b..188af070af 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -793,8 +793,7 @@ func buildCreateEndpointOptions(c *container.Container, n *libnetwork.Network, e var genericOptions = make(options.Generic) nwName := n.Name() - defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() - if c.NetworkSettings.IsAnonymousEndpoint || (nwName == defaultNetName && !serviceDiscoveryOnDefaultNetwork()) { + if c.NetworkSettings.IsAnonymousEndpoint { createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) } From dc1e73cbbff4451694308e6a8434cf824ec401b5 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Sat, 4 Nov 2023 15:22:40 +0100 Subject: [PATCH 02/10] libnet: add a new dnsNames property to Endpoint This new property is meant to replace myAliases and anonymous properties. The end goal is to get rid of both properties by letting the daemon determine what (non fully qualified) DNS names should be associated to them. Signed-off-by: Albin Kerouanton --- libnetwork/endpoint.go | 29 +++++++++++++++++++------- libnetwork/libnetwork_internal_test.go | 4 +++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 79a2689366..92e56532ea 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -23,14 +23,17 @@ type EndpointOption func(ep *Endpoint) // Endpoint represents a logical connection between a network and a sandbox. type Endpoint struct { - name string - id string - network *Network - iface *EndpointInterface - joinInfo *endpointJoinInfo - sandboxID string - exposedPorts []types.TransportPort - anonymous bool + name string + id string + network *Network + iface *EndpointInterface + joinInfo *endpointJoinInfo + sandboxID string + exposedPorts []types.TransportPort + anonymous bool + // dnsNames holds all the non-fully qualified DNS names associated to this endpoint. Order matters: first entry + // will be used for the PTR records associated to the endpoint's IPv4 and IPv6 addresses. + dnsNames []string disableResolution bool generic map[string]interface{} prefAddress net.IP @@ -65,6 +68,7 @@ func (ep *Endpoint) MarshalJSON() ([]byte, error) { } epMap["sandbox"] = ep.sandboxID epMap["anonymous"] = ep.anonymous + epMap["dnsNames"] = ep.dnsNames epMap["disableResolution"] = ep.disableResolution epMap["myAliases"] = ep.myAliases epMap["svcName"] = ep.svcName @@ -193,6 +197,12 @@ func (ep *Endpoint) UnmarshalJSON(b []byte) (err error) { var myAliases []string json.Unmarshal(ma, &myAliases) //nolint:errcheck ep.myAliases = myAliases + + dn, _ := json.Marshal(epMap["dnsNames"]) + var dnsNames []string + json.Unmarshal(dn, &dnsNames) + ep.dnsNames = dnsNames + return nil } @@ -243,6 +253,9 @@ func (ep *Endpoint) CopyTo(o datastore.KVObject) error { dstEp.myAliases = make([]string, len(ep.myAliases)) copy(dstEp.myAliases, ep.myAliases) + dstEp.dnsNames = make([]string, len(ep.dnsNames)) + copy(dstEp.dnsNames, ep.dnsNames) + dstEp.generic = options.Generic{} for k, v := range ep.generic { dstEp.generic[k] = v diff --git a/libnetwork/libnetwork_internal_test.go b/libnetwork/libnetwork_internal_test.go index b8259ccb19..2846f6367b 100644 --- a/libnetwork/libnetwork_internal_test.go +++ b/libnetwork/libnetwork_internal_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net" + "reflect" "runtime" "testing" "time" @@ -205,6 +206,7 @@ func TestEndpointMarshalling(t *testing.T) { v6PoolID: "poolv6", llAddrs: lla, }, + dnsNames: []string{"test", "foobar", "baz"}, } b, err := json.Marshal(e) @@ -218,7 +220,7 @@ func TestEndpointMarshalling(t *testing.T) { t.Fatal(err) } - if e.name != ee.name || e.id != ee.id || e.sandboxID != ee.sandboxID || !compareEndpointInterface(e.iface, ee.iface) || e.anonymous != ee.anonymous { + if e.name != ee.name || e.id != ee.id || e.sandboxID != ee.sandboxID || !reflect.DeepEqual(e.dnsNames, ee.dnsNames) || !compareEndpointInterface(e.iface, ee.iface) || e.anonymous != ee.anonymous { t.Fatalf("JSON marsh/unmarsh failed.\nOriginal:\n%#v\nDecoded:\n%#v\nOriginal iface: %#v\nDecodediface:\n%#v", e, ee, e.iface, ee.iface) } } From ab8968437bbb7dfde24e1ced19fe21bb9d2a4009 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Sat, 4 Nov 2023 14:12:20 +0100 Subject: [PATCH 03/10] daemon: build the list of endpoint's DNS names Instead of special-casing anonymous endpoints in libnetwork, let the daemon specify what (non fully qualified) DNS names should be associated to container's endpoints. Signed-off-by: Albin Kerouanton --- api/swagger.yaml | 15 ++++++++ api/types/network/endpoint.go | 11 +++++- daemon/container_operations.go | 27 ++++++++++++++ daemon/container_operations_test.go | 56 +++++++++++++++++++++++++++++ daemon/network.go | 3 ++ docs/api/version-history.md | 2 ++ internal/sliceutil/sliceutil.go | 13 +++++++ libnetwork/endpoint.go | 8 +++++ 8 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 daemon/container_operations_test.go create mode 100644 internal/sliceutil/sliceutil.go diff --git a/api/swagger.yaml b/api/swagger.yaml index 38759a3d03..b62ec2685b 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -2530,6 +2530,21 @@ definitions: example: com.example.some-label: "some-value" com.example.some-other-label: "some-other-value" + DNSNames: + description: | + List of all DNS names an endpoint has on a specific network. This + list is based on the container name, network aliases, container short + ID, and hostname. + + These DNS names are non-fully qualified but can contain several dots. + You can get fully qualified DNS names by appending `.`. + For instance, if container name is `my.ctr` and the network is named + `testnet`, `DNSNames` will contain `my.ctr` and the FQDN will be + `my.ctr.testnet`. + type: array + items: + type: string + example: ["foobar", "server_x", "server_y", "my.ctr"] EndpointIPAMConfig: description: | diff --git a/api/types/network/endpoint.go b/api/types/network/endpoint.go index d7d835f6d5..4b3c06a52b 100644 --- a/api/types/network/endpoint.go +++ b/api/types/network/endpoint.go @@ -13,7 +13,7 @@ type EndpointSettings struct { // Configurations IPAMConfig *EndpointIPAMConfig Links []string - Aliases []string + Aliases []string // Aliases holds the list of extra, user-specified DNS names for this endpoint. MacAddress string // Operational data NetworkID string @@ -25,6 +25,9 @@ type EndpointSettings struct { GlobalIPv6Address string GlobalIPv6PrefixLen int DriverOpts map[string]string + // DNSNames holds all the (non fully qualified) DNS names associated to this endpoint. First entry is used to + // generate PTR records. + DNSNames []string } // Copy makes a deep copy of `EndpointSettings` @@ -43,6 +46,12 @@ func (es *EndpointSettings) Copy() *EndpointSettings { aliases := make([]string, 0, len(es.Aliases)) epCopy.Aliases = append(aliases, es.Aliases...) } + + if len(es.DNSNames) > 0 { + epCopy.DNSNames = make([]string, len(es.DNSNames)) + copy(epCopy.DNSNames, es.DNSNames) + } + return &epCopy } diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 0d1596fe80..9b88845308 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -19,6 +19,7 @@ import ( "github.com/docker/docker/daemon/network" "github.com/docker/docker/errdefs" "github.com/docker/docker/internal/multierror" + "github.com/docker/docker/internal/sliceutil" "github.com/docker/docker/libnetwork" "github.com/docker/docker/libnetwork/netlabel" "github.com/docker/docker/libnetwork/options" @@ -650,6 +651,9 @@ func cleanOperationalData(es *network.EndpointSettings) { func (daemon *Daemon) updateNetworkConfig(container *container.Container, n *libnetwork.Network, endpointConfig *networktypes.EndpointSettings, updateSettings bool) error { if containertypes.NetworkMode(n.Name()).IsUserDefined() { + endpointConfig.DNSNames = buildEndpointDNSNames(container, endpointConfig.Aliases) + + // TODO(aker): remove this code once endpoint's DNSNames is used for real. addShortID := true shortID := stringid.TruncateID(container.ID) for _, alias := range endpointConfig.Aliases { @@ -687,6 +691,29 @@ func (daemon *Daemon) updateNetworkConfig(container *container.Container, n *lib return nil } +// buildEndpointDNSNames constructs the list of DNSNames that should be assigned to a given endpoint. The order within +// the returned slice is important as the first entry will be used to generate the PTR records (for IPv4 and v6) +// associated to this endpoint. +func buildEndpointDNSNames(ctr *container.Container, aliases []string) []string { + var dnsNames []string + + if ctr.Name != "" { + dnsNames = append(dnsNames, strings.TrimPrefix(ctr.Name, "/")) + } + + dnsNames = append(dnsNames, aliases...) + + if ctr.ID != "" { + dnsNames = append(dnsNames, stringid.TruncateID(ctr.ID)) + } + + if ctr.Config.Hostname != "" { + dnsNames = append(dnsNames, ctr.Config.Hostname) + } + + return sliceutil.Dedup(dnsNames) +} + func (daemon *Daemon) connectToNetwork(cfg *config.Config, container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { start := time.Now() if container.HostConfig.NetworkMode.IsContainer() { diff --git a/daemon/container_operations_test.go b/daemon/container_operations_test.go new file mode 100644 index 0000000000..cae813eec7 --- /dev/null +++ b/daemon/container_operations_test.go @@ -0,0 +1,56 @@ +package daemon + +import ( + "encoding/json" + "testing" + + containertypes "github.com/docker/docker/api/types/container" + networktypes "github.com/docker/docker/api/types/network" + "github.com/docker/docker/container" + "github.com/docker/docker/libnetwork" + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" +) + +func TestDNSNamesAreEquivalentToAliases(t *testing.T) { + d := &Daemon{} + ctr := &container.Container{ + ID: "35de8003b19e27f636fc6ecbf4d7072558b872a8544f287fd69ad8182ad59023", + Name: "foobar", + Config: &containertypes.Config{ + Hostname: "baz", + }, + } + nw := buildNetwork(t, map[string]any{ + "id": "1234567890", + "name": "testnet", + "networkType": "bridge", + "enableIPv6": false, + }) + epSettings := &networktypes.EndpointSettings{ + Aliases: []string{"myctr"}, + } + + if err := d.updateNetworkConfig(ctr, nw, epSettings, false); err != nil { + t.Fatal(err) + } + + assert.Check(t, is.DeepEqual(epSettings.Aliases, []string{"myctr", "35de8003b19e", "baz"})) + assert.Check(t, is.DeepEqual(epSettings.DNSNames, []string{"foobar", "myctr", "35de8003b19e", "baz"})) +} + +func buildNetwork(t *testing.T, config map[string]any) *libnetwork.Network { + t.Helper() + + b, err := json.Marshal(config) + if err != nil { + t.Fatal(err) + } + + nw := &libnetwork.Network{} + if err := nw.UnmarshalJSON(b); err != nil { + t.Fatal(err) + } + + return nw +} diff --git a/daemon/network.go b/daemon/network.go index 188af070af..77b3069d08 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -821,9 +821,12 @@ func buildCreateEndpointOptions(c *container.Container, n *libnetwork.Network, e createOptions = append(createOptions, libnetwork.CreateOptionIpam(ip, ip6, ipList, nil)) } + // TODO(aker): remove this loop once endpoint's DNSNames is used for real for _, alias := range epConfig.Aliases { createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias)) } + createOptions = append(createOptions, libnetwork.CreateOptionDNSNames(epConfig.DNSNames)) + for k, v := range epConfig.DriverOpts { createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v})) } diff --git a/docs/api/version-history.md b/docs/api/version-history.md index 4dcff253f2..748e435ab3 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -68,6 +68,8 @@ keywords: "API, Docker, rcli, REST, documentation" * The `Container` and `ContainerConfig` fields in the `GET /images/{name}/json` response are deprecated and will no longer be included in API v1.45. * `GET /info` now includes `status` properties in `Runtimes`. +* A new field named `DNSNames` and containing all non-fully qualified DNS names + a container takes on a specific network has been added to `GET /containers/{name:.*}/json`. ## v1.43 API changes diff --git a/internal/sliceutil/sliceutil.go b/internal/sliceutil/sliceutil.go new file mode 100644 index 0000000000..66d90f2dc9 --- /dev/null +++ b/internal/sliceutil/sliceutil.go @@ -0,0 +1,13 @@ +package sliceutil + +func Dedup[T comparable](slice []T) []T { + keys := make(map[T]struct{}) + out := make([]T, 0, len(slice)) + for _, s := range slice { + if _, ok := keys[s]; !ok { + out = append(out, s) + keys[s] = struct{}{} + } + } + return out +} diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 92e56532ea..5fbcc03f5c 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -972,6 +972,14 @@ func CreateOptionAnonymous() EndpointOption { } } +// CreateOptionDNSNames specifies the list of (non fully qualified) DNS names associated to an endpoint. These will be +// used to populate the embedded DNS server. Order matters: first name will be used to generate PTR records. +func CreateOptionDNSNames(names []string) EndpointOption { + return func(ep *Endpoint) { + ep.dnsNames = names + } +} + // CreateOptionDisableResolution function returns an option setter to indicate // this endpoint doesn't want embedded DNS server functionality func CreateOptionDisableResolution() EndpointOption { From f5cc497eac4cdacbb806978cc2de018244c06e98 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Tue, 28 Nov 2023 11:48:11 +0100 Subject: [PATCH 04/10] libnet: populate Endpoint.dnsNames on UnmarshalJSON This new property will be empty if the daemon was upgraded with live-restore enabled. To not break DNS resolutions for restored containers, we need to populate dnsNames based on endpoint's myAliases & anonymous properties. Signed-off-by: Albin Kerouanton --- libnetwork/endpoint.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 5fbcc03f5c..177e6d75dd 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/containerd/log" + "github.com/docker/docker/internal/sliceutil" "github.com/docker/docker/libnetwork/datastore" "github.com/docker/docker/libnetwork/ipamapi" "github.com/docker/docker/libnetwork/netlabel" @@ -198,11 +199,22 @@ func (ep *Endpoint) UnmarshalJSON(b []byte) (err error) { json.Unmarshal(ma, &myAliases) //nolint:errcheck ep.myAliases = myAliases + _, hasDNSNames := epMap["dnsNames"] dn, _ := json.Marshal(epMap["dnsNames"]) var dnsNames []string json.Unmarshal(dn, &dnsNames) ep.dnsNames = dnsNames + // TODO(aker): remove this migration code in v27 + if !hasDNSNames { + // The field dnsNames was introduced in v25.0. If we don't have it, the on-disk state was written by an older + // daemon, thus we need to populate dnsNames based off of myAliases and anonymous values. + if !ep.anonymous { + myAliases = append([]string{ep.name}, myAliases...) + } + ep.dnsNames = sliceutil.Dedup(myAliases) + } + return nil } From 3bb13c7eb4f50611fcf74f985176d8d4da76f6e7 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Sat, 4 Nov 2023 15:12:21 +0100 Subject: [PATCH 05/10] libnet: Use Endpoint.dnsNames to create DNS records Instead of special-casing anonymous endpoints, use the list of DNS names associated to the endpoint. `(*Endpoint).isAnonymous()` has no more uses, so let's delete it. Signed-off-by: Albin Kerouanton --- libnetwork/agent.go | 28 ++++++++++++---------------- libnetwork/endpoint.go | 9 +++++++-- libnetwork/network.go | 32 +++++++++----------------------- 3 files changed, 28 insertions(+), 41 deletions(-) diff --git a/libnetwork/agent.go b/libnetwork/agent.go index 3ff97c53a0..be3091fd0f 100644 --- a/libnetwork/agent.go +++ b/libnetwork/agent.go @@ -598,7 +598,7 @@ func (ep *Endpoint) deleteDriverInfoFromCluster() error { } func (ep *Endpoint) addServiceInfoToCluster(sb *Sandbox) error { - if len(ep.myAliases) == 0 && ep.isAnonymous() || ep.Iface() == nil || ep.Iface().Address() == nil { + if len(ep.dnsNames) == 0 || ep.Iface() == nil || ep.Iface().Address() == nil { return nil } @@ -628,10 +628,8 @@ func (ep *Endpoint) addServiceInfoToCluster(sb *Sandbox) error { return nil } - name := ep.Name() - if ep.isAnonymous() { - name = ep.MyAliases()[0] - } + dnsNames := ep.getDNSNames() + primaryDNSName, dnsAliases := dnsNames[0], dnsNames[1:] var ingressPorts []*PortConfig if ep.svcID != "" { @@ -640,24 +638,24 @@ func (ep *Endpoint) addServiceInfoToCluster(sb *Sandbox) error { if n.ingress { ingressPorts = ep.ingressPorts } - if err := n.getController().addServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), name, ep.virtualIP, ingressPorts, ep.svcAliases, ep.myAliases, ep.Iface().Address().IP, "addServiceInfoToCluster"); err != nil { + if err := n.getController().addServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), primaryDNSName, ep.virtualIP, ingressPorts, ep.svcAliases, dnsAliases, ep.Iface().Address().IP, "addServiceInfoToCluster"); err != nil { return err } } else { // This is a container simply attached to an attachable network - if err := n.getController().addContainerNameResolution(n.ID(), ep.ID(), name, ep.myAliases, ep.Iface().Address().IP, "addServiceInfoToCluster"); err != nil { + if err := n.getController().addContainerNameResolution(n.ID(), ep.ID(), primaryDNSName, dnsAliases, ep.Iface().Address().IP, "addServiceInfoToCluster"); err != nil { return err } } buf, err := proto.Marshal(&EndpointRecord{ - Name: name, + Name: primaryDNSName, ServiceName: ep.svcName, ServiceID: ep.svcID, VirtualIP: ep.virtualIP.String(), IngressPorts: ingressPorts, Aliases: ep.svcAliases, - TaskAliases: ep.myAliases, + TaskAliases: dnsAliases, EndpointIP: ep.Iface().Address().IP.String(), ServiceDisabled: false, }) @@ -676,7 +674,7 @@ func (ep *Endpoint) addServiceInfoToCluster(sb *Sandbox) error { } func (ep *Endpoint) deleteServiceInfoFromCluster(sb *Sandbox, fullRemove bool, method string) error { - if len(ep.myAliases) == 0 && ep.isAnonymous() { + if len(ep.dnsNames) == 0 { return nil } @@ -699,10 +697,8 @@ func (ep *Endpoint) deleteServiceInfoFromCluster(sb *Sandbox, fullRemove bool, m return nil } - name := ep.Name() - if ep.isAnonymous() { - name = ep.MyAliases()[0] - } + dnsNames := ep.getDNSNames() + primaryDNSName, dnsAliases := dnsNames[0], dnsNames[1:] // First update the networkDB then locally if fullRemove { @@ -720,12 +716,12 @@ func (ep *Endpoint) deleteServiceInfoFromCluster(sb *Sandbox, fullRemove bool, m if n.ingress { ingressPorts = ep.ingressPorts } - if err := n.getController().rmServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), name, ep.virtualIP, ingressPorts, ep.svcAliases, ep.myAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster", true, fullRemove); err != nil { + if err := n.getController().rmServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), primaryDNSName, ep.virtualIP, ingressPorts, ep.svcAliases, dnsAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster", true, fullRemove); err != nil { return err } } else { // This is a container simply attached to an attachable network - if err := n.getController().delContainerNameResolution(n.ID(), ep.ID(), name, ep.myAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster"); err != nil { + if err := n.getController().delContainerNameResolution(n.ID(), ep.ID(), primaryDNSName, dnsAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster"); err != nil { return err } } diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 177e6d75dd..30fef4d4ec 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -308,10 +308,15 @@ func (ep *Endpoint) Network() string { return ep.network.name } -func (ep *Endpoint) isAnonymous() bool { +// getDNSNames returns a copy of the DNS names associated to this endpoint. The first entry is the one used for PTR +// records. +func (ep *Endpoint) getDNSNames() []string { ep.mu.Lock() defer ep.mu.Unlock() - return ep.anonymous + + dnsNames := make([]string, len(ep.dnsNames)) + copy(dnsNames, ep.dnsNames) + return dnsNames } // isServiceEnabled check if service is enabled on the endpoint diff --git a/libnetwork/network.go b/libnetwork/network.go index 75c5de5cad..fced1c458f 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -1302,8 +1302,6 @@ func (n *Network) updateSvcRecord(ep *Endpoint, isAdd bool) { } var ipv6 net.IP - epName := ep.Name() - myAliases := ep.MyAliases() if iface.AddressIPv6() != nil { ipv6 = iface.AddressIPv6().IP } @@ -1312,30 +1310,17 @@ func (n *Network) updateSvcRecord(ep *Endpoint, isAdd bool) { if serviceID == "" { serviceID = ep.ID() } + + dnsNames := ep.getDNSNames() if isAdd { - // If anonymous endpoint has an alias use the first alias - // for ip->name mapping. Not having the reverse mapping - // breaks some apps - if ep.isAnonymous() { - if len(myAliases) > 0 { - n.addSvcRecords(ep.ID(), myAliases[0], serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") - } - } else { - n.addSvcRecords(ep.ID(), epName, serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") - } - for _, alias := range myAliases { - n.addSvcRecords(ep.ID(), alias, serviceID, iface.Address().IP, ipv6, false, "updateSvcRecord") + 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") } } else { - if ep.isAnonymous() { - if len(myAliases) > 0 { - n.deleteSvcRecords(ep.ID(), myAliases[0], serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") - } - } else { - n.deleteSvcRecords(ep.ID(), epName, serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") - } - for _, alias := range myAliases { - n.deleteSvcRecords(ep.ID(), alias, serviceID, iface.Address().IP, ipv6, false, "updateSvcRecord") + 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") } } } @@ -1374,6 +1359,7 @@ 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) { // Do not add service names for ingress network as this is a // routing only network From 8b7af1d0fc5b890038b7776dd4155b41c28f52d9 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Tue, 7 Nov 2023 13:45:20 +0100 Subject: [PATCH 06/10] libnet: update dnsNames on ContainerRename The `(*Endpoint).rename()` method is changed to only mutate `ep.name` and let a new method `(*Endpoint).UpdateDNSNames()` handle DNS updates. As a consequence, the rollback code that was part of `(*Endpoint).rename()` is now removed, and DNS updates are now rolled back by `ContainerRename`. Signed-off-by: Albin Kerouanton --- daemon/rename.go | 52 ++++++++++++++++++++++++++++-- libnetwork/endpoint.go | 73 ++++++++++++++++-------------------------- 2 files changed, 77 insertions(+), 48 deletions(-) diff --git a/daemon/rename.go b/daemon/rename.go index d758d899b2..059ca5b0b1 100644 --- a/daemon/rename.go +++ b/daemon/rename.go @@ -7,6 +7,7 @@ import ( "github.com/containerd/log" "github.com/docker/docker/api/types/events" dockercontainer "github.com/docker/docker/container" + "github.com/docker/docker/daemon/network" "github.com/docker/docker/errdefs" "github.com/docker/docker/libnetwork" "github.com/pkg/errors" @@ -118,10 +119,57 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) (retErr error) { return err } - err = sb.Rename(strings.TrimPrefix(container.Name, "/")) - if err != nil { + if err := sb.Rename(newName[1:]); err != nil { return err } + defer func() { + if retErr != nil { + if err := sb.Rename(oldName); err != nil { + log.G(context.TODO()).WithFields(log.Fields{ + "sandboxID": sid, + "oldName": oldName, + "newName": newName, + "error": err, + }).Errorf("failed to revert sandbox rename") + } + } + }() + + for nwName, epConfig := range container.NetworkSettings.Networks { + nw, err := daemon.FindNetwork(nwName) + if err != nil { + return err + } + + ep, err := nw.EndpointByID(epConfig.EndpointID) + if err != nil { + return err + } + + oldDNSNames := make([]string, len(epConfig.DNSNames)) + copy(oldDNSNames, epConfig.DNSNames) + + epConfig.DNSNames = buildEndpointDNSNames(container, epConfig.Aliases) + if err := ep.UpdateDNSNames(epConfig.DNSNames); err != nil { + return err + } + + defer func(ep *libnetwork.Endpoint, epConfig *network.EndpointSettings, oldDNSNames []string) { + if retErr == nil { + return + } + + epConfig.DNSNames = oldDNSNames + if err := ep.UpdateDNSNames(epConfig.DNSNames); err != nil { + log.G(context.TODO()).WithFields(log.Fields{ + "sandboxID": sid, + "oldName": oldName, + "newName": newName, + "error": err, + }).Errorf("failed to revert DNSNames update") + } + }(ep, epConfig, oldDNSNames) + } } daemon.LogContainerEventWithAttributes(container, events.ActionRename, attributes) diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 30fef4d4ec..fc88e8b574 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -598,71 +598,52 @@ func (ep *Endpoint) sbJoin(sb *Sandbox, options ...EndpointOption) (err error) { } func (ep *Endpoint) rename(name string) error { - var ( - err error - ok bool - ) + ep.mu.Lock() + ep.name = name + ep.mu.Unlock() - n := ep.getNetwork() - if n == nil { - return fmt.Errorf("network not connected for ep %q", ep.name) + // Update the store with the updated name + if err := ep.getNetwork().getController().updateToStore(ep); err != nil { + return err } - c := n.getController() + return nil +} +func (ep *Endpoint) UpdateDNSNames(dnsNames []string) error { + nw := ep.getNetwork() + c := nw.getController() sb, ok := ep.getSandbox() if !ok { - log.G(context.TODO()).Warnf("rename for %s aborted, sandbox %s is not anymore present", ep.ID(), ep.sandboxID) + log.G(context.TODO()).WithFields(log.Fields{ + "sandboxID": ep.sandboxID, + "endpointID": ep.ID(), + }).Warn("DNSNames update aborted, sandbox is not present anymore") return nil } if c.isAgent() { - if err = ep.deleteServiceInfoFromCluster(sb, true, "rename"); err != nil { - return types.InternalErrorf("Could not delete service state for endpoint %s from cluster on rename: %v", ep.Name(), err) + if err := ep.deleteServiceInfoFromCluster(sb, true, "UpdateDNSNames"); err != nil { + return types.InternalErrorf("could not delete service state for endpoint %s from cluster on UpdateDNSNames: %v", ep.Name(), err) + } + + ep.dnsNames = dnsNames + if err := ep.addServiceInfoToCluster(sb); err != nil { + return types.InternalErrorf("could not add service state for endpoint %s to cluster on UpdateDNSNames: %v", ep.Name(), err) } } else { - n.updateSvcRecord(ep, false) - } + nw.updateSvcRecord(ep, false) - oldName := ep.name - oldAnonymous := ep.anonymous - ep.name = name - ep.anonymous = false - - if c.isAgent() { - if err = ep.addServiceInfoToCluster(sb); err != nil { - return types.InternalErrorf("Could not add service state for endpoint %s to cluster on rename: %v", ep.Name(), err) - } - defer func() { - if err != nil { - if err2 := ep.deleteServiceInfoFromCluster(sb, true, "rename"); err2 != nil { - log.G(context.TODO()).WithField("main error", err).WithError(err2).Debug("Error during cleanup due deleting service info from cluster while cleaning up due to other error") - } - ep.name = oldName - ep.anonymous = oldAnonymous - if err2 := ep.addServiceInfoToCluster(sb); err2 != nil { - log.G(context.TODO()).WithField("main error", err).WithError(err2).Debug("Error during cleanup due adding service to from cluster while cleaning up due to other error") - } - } - }() - } else { - n.updateSvcRecord(ep, true) - defer func() { - if err != nil { - n.updateSvcRecord(ep, false) - ep.name = oldName - ep.anonymous = oldAnonymous - n.updateSvcRecord(ep, true) - } - }() + ep.dnsNames = dnsNames + nw.updateSvcRecord(ep, true) } // Update the store with the updated name - if err = c.updateToStore(ep); err != nil { + if err := c.updateToStore(ep); err != nil { return err } - return err + return nil } func (ep *Endpoint) hasInterface(iName string) bool { From 523b9073596a68be5caff25e5163a2190f7e05e6 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Sat, 4 Nov 2023 13:07:00 +0100 Subject: [PATCH 07/10] daemon: no more IsAnonymousEndpoint The semantics of an "anonymous" endpoint has always been weird: it was set on endpoints which name shouldn't be taken into account when inserting DNS records into libnetwork's `Controller.svcRecords` (and into the NetworkDB). However, in that case the endpoint's aliases would still be used to create DNS records; thus, making those "anonymous endpoints" not so anonymous. Signed-off-by: Albin Kerouanton --- daemon/container.go | 7 +++---- daemon/network.go | 3 --- daemon/network/settings.go | 1 - daemon/rename.go | 4 ---- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/daemon/container.go b/daemon/container.go index d2494481b6..ccf29e27cf 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -122,9 +122,8 @@ func (daemon *Daemon) Register(c *container.Container) error { func (daemon *Daemon) newContainer(name string, operatingSystem string, config *containertypes.Config, hostConfig *containertypes.HostConfig, imgID image.ID, managed bool) (*container.Container, error) { var ( - id string - err error - noExplicitName = name == "" + id string + err error ) id, name, err = daemon.generateIDAndName(name) if err != nil { @@ -151,7 +150,7 @@ func (daemon *Daemon) newContainer(name string, operatingSystem string, config * base.Config = config base.HostConfig = &containertypes.HostConfig{} base.ImageID = imgID - base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName} + base.NetworkSettings = &network.Settings{} base.Name = name base.Driver = daemon.imageService.StorageDriver() base.OS = operatingSystem diff --git a/daemon/network.go b/daemon/network.go index 77b3069d08..0fd4d89501 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -793,9 +793,6 @@ func buildCreateEndpointOptions(c *container.Container, n *libnetwork.Network, e var genericOptions = make(options.Generic) nwName := n.Name() - if c.NetworkSettings.IsAnonymousEndpoint { - createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) - } if epConfig != nil { if ipam := epConfig.IPAMConfig; ipam != nil { diff --git a/daemon/network/settings.go b/daemon/network/settings.go index a39cab5a60..c31b139ae8 100644 --- a/daemon/network/settings.go +++ b/daemon/network/settings.go @@ -24,7 +24,6 @@ type Settings struct { Ports nat.PortMap SecondaryIPAddresses []networktypes.Address SecondaryIPv6Addresses []networktypes.Address - IsAnonymousEndpoint bool HasSwarmEndpoint bool } diff --git a/daemon/rename.go b/daemon/rename.go index 059ca5b0b1..728796d657 100644 --- a/daemon/rename.go +++ b/daemon/rename.go @@ -39,7 +39,6 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) (retErr error) { defer container.Unlock() oldName = container.Name - oldIsAnonymousEndpoint := container.NetworkSettings.IsAnonymousEndpoint if oldName == newName { return errdefs.InvalidParameter(errors.New("Renaming a container with the same name as its current name")) @@ -63,12 +62,10 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) (retErr error) { } container.Name = newName - container.NetworkSettings.IsAnonymousEndpoint = false defer func() { if retErr != nil { container.Name = oldName - container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint daemon.reserveName(container.ID, oldName) for k, v := range links { daemon.containersReplica.ReserveName(oldName+k, v.ID) @@ -102,7 +99,6 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) (retErr error) { defer func() { if retErr != nil { container.Name = oldName - container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint if err := container.CheckpointTo(daemon.containersReplica); err != nil { log.G(context.TODO()).WithFields(log.Fields{ "containerID": container.ID, From 7a9b680a9c17ad0ac5caff8826ef9a63abcc7594 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Sat, 4 Nov 2023 16:27:57 +0100 Subject: [PATCH 08/10] libnet: remove Endpoint.myAliases This property is now unused, let's get rid of it. Signed-off-by: Albin Kerouanton --- daemon/container_operations.go | 25 ------------------------- daemon/container_operations_test.go | 3 +-- daemon/network.go | 4 ---- libnetwork/endpoint.go | 20 -------------------- 4 files changed, 1 insertion(+), 51 deletions(-) diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 9b88845308..ff7056295c 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -652,31 +652,6 @@ func cleanOperationalData(es *network.EndpointSettings) { func (daemon *Daemon) updateNetworkConfig(container *container.Container, n *libnetwork.Network, endpointConfig *networktypes.EndpointSettings, updateSettings bool) error { if containertypes.NetworkMode(n.Name()).IsUserDefined() { endpointConfig.DNSNames = buildEndpointDNSNames(container, endpointConfig.Aliases) - - // TODO(aker): remove this code once endpoint's DNSNames is used for real. - addShortID := true - shortID := stringid.TruncateID(container.ID) - for _, alias := range endpointConfig.Aliases { - if alias == shortID { - addShortID = false - break - } - } - if addShortID { - endpointConfig.Aliases = append(endpointConfig.Aliases, shortID) - } - if container.Name != container.Config.Hostname { - addHostname := true - for _, alias := range endpointConfig.Aliases { - if alias == container.Config.Hostname { - addHostname = false - break - } - } - if addHostname { - endpointConfig.Aliases = append(endpointConfig.Aliases, container.Config.Hostname) - } - } } if err := validateEndpointSettings(n, n.Name(), endpointConfig); err != nil { diff --git a/daemon/container_operations_test.go b/daemon/container_operations_test.go index cae813eec7..aa86a10a0c 100644 --- a/daemon/container_operations_test.go +++ b/daemon/container_operations_test.go @@ -12,7 +12,7 @@ import ( is "gotest.tools/v3/assert/cmp" ) -func TestDNSNamesAreEquivalentToAliases(t *testing.T) { +func TestDNSNamesOrder(t *testing.T) { d := &Daemon{} ctr := &container.Container{ ID: "35de8003b19e27f636fc6ecbf4d7072558b872a8544f287fd69ad8182ad59023", @@ -35,7 +35,6 @@ func TestDNSNamesAreEquivalentToAliases(t *testing.T) { t.Fatal(err) } - assert.Check(t, is.DeepEqual(epSettings.Aliases, []string{"myctr", "35de8003b19e", "baz"})) assert.Check(t, is.DeepEqual(epSettings.DNSNames, []string{"foobar", "myctr", "35de8003b19e", "baz"})) } diff --git a/daemon/network.go b/daemon/network.go index 0fd4d89501..c4b0c93c1d 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -818,10 +818,6 @@ func buildCreateEndpointOptions(c *container.Container, n *libnetwork.Network, e createOptions = append(createOptions, libnetwork.CreateOptionIpam(ip, ip6, ipList, nil)) } - // TODO(aker): remove this loop once endpoint's DNSNames is used for real - for _, alias := range epConfig.Aliases { - createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias)) - } createOptions = append(createOptions, libnetwork.CreateOptionDNSNames(epConfig.DNSNames)) for k, v := range epConfig.DriverOpts { diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index fc88e8b574..067b8e56d2 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -41,7 +41,6 @@ type Endpoint struct { prefAddressV6 net.IP ipamOptions map[string]string aliases map[string]string - myAliases []string svcID string svcName string virtualIP net.IP @@ -71,7 +70,6 @@ func (ep *Endpoint) MarshalJSON() ([]byte, error) { epMap["anonymous"] = ep.anonymous epMap["dnsNames"] = ep.dnsNames epMap["disableResolution"] = ep.disableResolution - epMap["myAliases"] = ep.myAliases epMap["svcName"] = ep.svcName epMap["svcID"] = ep.svcID epMap["virtualIP"] = ep.virtualIP.String() @@ -197,7 +195,6 @@ func (ep *Endpoint) UnmarshalJSON(b []byte) (err error) { ma, _ := json.Marshal(epMap["myAliases"]) var myAliases []string json.Unmarshal(ma, &myAliases) //nolint:errcheck - ep.myAliases = myAliases _, hasDNSNames := epMap["dnsNames"] dn, _ := json.Marshal(epMap["dnsNames"]) @@ -262,9 +259,6 @@ func (ep *Endpoint) CopyTo(o datastore.KVObject) error { dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts)) copy(dstEp.exposedPorts, ep.exposedPorts) - dstEp.myAliases = make([]string, len(ep.myAliases)) - copy(dstEp.myAliases, ep.myAliases) - dstEp.dnsNames = make([]string, len(ep.dnsNames)) copy(dstEp.dnsNames, ep.dnsNames) @@ -292,13 +286,6 @@ func (ep *Endpoint) Name() string { return ep.name } -func (ep *Endpoint) MyAliases() []string { - ep.mu.Lock() - defer ep.mu.Unlock() - - return ep.myAliases -} - // Network returns the name of the network to which this endpoint is attached. func (ep *Endpoint) Network() string { if ep.network == nil { @@ -1007,13 +994,6 @@ func CreateOptionService(name, id string, vip net.IP, ingressPorts []*PortConfig } } -// CreateOptionMyAlias function returns an option setter for setting endpoint's self alias -func CreateOptionMyAlias(alias string) EndpointOption { - return func(ep *Endpoint) { - ep.myAliases = append(ep.myAliases, alias) - } -} - // CreateOptionLoadBalancer function returns an option setter for denoting the endpoint is a load balancer for a network func CreateOptionLoadBalancer() EndpointOption { return func(ep *Endpoint) { From 6a2542dacfb3821f980f44b33f3bbe7da1db337b Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Wed, 29 Nov 2023 23:02:56 +0100 Subject: [PATCH 09/10] libnet: remove Endpoint.anonymous No more concept of "anonymous endpoints". The equivalent is now an endpoint with no DNSNames set. Some of the code removed by this commit was mutating user-supplied endpoint's Aliases to add container's short ID to that list. In order to preserve backward compatibility for the ContainerInspect endpoint, this commit also takes care of adding that short ID (and the container hostname) to `EndpointSettings.Aliases` before returning the response. Signed-off-by: Albin Kerouanton --- daemon/inspect.go | 14 ++++++++++++++ docs/api/version-history.md | 5 +++++ hack/make/test-docker-py | 3 ++- integration/service/network_test.go | 5 +++-- libnetwork/default_gateway.go | 2 +- libnetwork/endpoint.go | 16 +++------------- libnetwork/libnetwork_internal_test.go | 3 +-- libnetwork/network.go | 4 ---- 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/daemon/inspect.go b/daemon/inspect.go index c017572502..1c9285fd97 100644 --- a/daemon/inspect.go +++ b/daemon/inspect.go @@ -15,6 +15,8 @@ import ( "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/network" "github.com/docker/docker/errdefs" + "github.com/docker/docker/internal/sliceutil" + "github.com/docker/docker/pkg/stringid" "github.com/docker/go-connections/nat" ) @@ -27,6 +29,18 @@ func (daemon *Daemon) ContainerInspect(ctx context.Context, name string, size bo return daemon.containerInspectPre120(ctx, name) case versions.Equal(version, "1.20"): return daemon.containerInspect120(name) + case versions.LessThan(version, "1.45"): + ctr, err := daemon.ContainerInspectCurrent(ctx, name, size) + if err != nil { + return nil, err + } + + shortCID := stringid.TruncateID(ctr.ID) + for _, ep := range ctr.NetworkSettings.Networks { + ep.Aliases = sliceutil.Dedup(append(ep.Aliases, shortCID, ctr.Config.Hostname)) + } + + return ctr, nil default: return daemon.ContainerInspectCurrent(ctx, name, size) } diff --git a/docs/api/version-history.md b/docs/api/version-history.md index 748e435ab3..4efde2bcb5 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -70,6 +70,11 @@ keywords: "API, Docker, rcli, REST, documentation" * `GET /info` now includes `status` properties in `Runtimes`. * A new field named `DNSNames` and containing all non-fully qualified DNS names a container takes on a specific network has been added to `GET /containers/{name:.*}/json`. +* The `Aliases` field returned in calls to `GET /containers/{name:.*}/json` in v1.44 and older + versions contains the short container ID. This will change in the next API version, v1.45. + Starting with that API version, this specific value will be removed from the `Aliases` field + such that this field will reflect exactly the values originally submitted to the + `POST /containers/create` endpoint. The newly introduced `DNSNames` should now be used instead. ## v1.43 API changes diff --git a/hack/make/test-docker-py b/hack/make/test-docker-py index 28646d3935..0e40d8f3ce 100644 --- a/hack/make/test-docker-py +++ b/hack/make/test-docker-py @@ -13,7 +13,8 @@ source hack/make/.integration-test-helpers # --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_attach_no_stream # TODO re-enable test_attach_no_stream after https://github.com/docker/docker-py/issues/2513 is resolved # TODO re-enable test_run_container_reading_socket_ws. It's reported in https://github.com/docker/docker-py/issues/1478, and we're getting that error in our tests. -: "${PY_TEST_OPTIONS:=--junitxml=${DEST}/junit-report.xml --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_attach_no_stream --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_run_container_reading_socket_ws}" +# TODO re-enable test_run_with_networking_config once this issue is fixed: https://github.com/moby/moby/pull/46853#issuecomment-1864679942. +: "${PY_TEST_OPTIONS:=--junitxml=${DEST}/junit-report.xml --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_attach_no_stream --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_run_container_reading_socket_ws --deselect=tests/integration/models_containers_test.py::ContainerCollectionTest::test_run_with_networking_config}" # build --squash is not supported with containerd integration. if [ -n "$TEST_INTEGRATION_USE_SNAPSHOTTER" ]; then diff --git a/integration/service/network_test.go b/integration/service/network_test.go index d1fb6372f0..ba4a18a68c 100644 --- a/integration/service/network_test.go +++ b/integration/service/network_test.go @@ -5,6 +5,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" net "github.com/docker/docker/integration/internal/network" "github.com/docker/docker/integration/internal/swarm" @@ -13,13 +14,13 @@ import ( "gotest.tools/v3/skip" ) -func TestDockerNetworkConnectAlias(t *testing.T) { +func TestDockerNetworkConnectAliasPreV144(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") ctx := setupTest(t) d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) - client := d.NewClientT(t) + client := d.NewClientT(t, client.WithVersion("1.43")) defer client.Close() name := t.Name() + "test-alias" diff --git a/libnetwork/default_gateway.go b/libnetwork/default_gateway.go index 8e7b9981bd..651fee3f75 100644 --- a/libnetwork/default_gateway.go +++ b/libnetwork/default_gateway.go @@ -47,7 +47,7 @@ func (sb *Sandbox) setupDefaultGW() error { } } - createOptions := []EndpointOption{CreateOptionAnonymous()} + createOptions := []EndpointOption{} var gwName string if len(sb.containerID) <= gwEPlen { diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 067b8e56d2..608fb8bf02 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -31,7 +31,6 @@ type Endpoint struct { joinInfo *endpointJoinInfo sandboxID string exposedPorts []types.TransportPort - anonymous bool // dnsNames holds all the non-fully qualified DNS names associated to this endpoint. Order matters: first entry // will be used for the PTR records associated to the endpoint's IPv4 and IPv6 addresses. dnsNames []string @@ -67,7 +66,6 @@ func (ep *Endpoint) MarshalJSON() ([]byte, error) { epMap["generic"] = ep.generic } epMap["sandbox"] = ep.sandboxID - epMap["anonymous"] = ep.anonymous epMap["dnsNames"] = ep.dnsNames epMap["disableResolution"] = ep.disableResolution epMap["svcName"] = ep.svcName @@ -159,8 +157,9 @@ func (ep *Endpoint) UnmarshalJSON(b []byte) (err error) { } } + var anonymous bool if v, ok := epMap["anonymous"]; ok { - ep.anonymous = v.(bool) + anonymous = v.(bool) } if v, ok := epMap["disableResolution"]; ok { ep.disableResolution = v.(bool) @@ -206,7 +205,7 @@ func (ep *Endpoint) UnmarshalJSON(b []byte) (err error) { if !hasDNSNames { // The field dnsNames was introduced in v25.0. If we don't have it, the on-disk state was written by an older // daemon, thus we need to populate dnsNames based off of myAliases and anonymous values. - if !ep.anonymous { + if !anonymous { myAliases = append([]string{ep.name}, myAliases...) } ep.dnsNames = sliceutil.Dedup(myAliases) @@ -229,7 +228,6 @@ func (ep *Endpoint) CopyTo(o datastore.KVObject) error { dstEp.sandboxID = ep.sandboxID dstEp.dbIndex = ep.dbIndex dstEp.dbExists = ep.dbExists - dstEp.anonymous = ep.anonymous dstEp.disableResolution = ep.disableResolution dstEp.svcName = ep.svcName dstEp.svcID = ep.svcID @@ -949,14 +947,6 @@ func CreateOptionDNS(dns []string) EndpointOption { } } -// CreateOptionAnonymous function returns an option setter for setting -// this endpoint as anonymous -func CreateOptionAnonymous() EndpointOption { - return func(ep *Endpoint) { - ep.anonymous = true - } -} - // CreateOptionDNSNames specifies the list of (non fully qualified) DNS names associated to an endpoint. These will be // used to populate the embedded DNS server. Order matters: first name will be used to generate PTR records. func CreateOptionDNSNames(names []string) EndpointOption { diff --git a/libnetwork/libnetwork_internal_test.go b/libnetwork/libnetwork_internal_test.go index 2846f6367b..ef42dba7bf 100644 --- a/libnetwork/libnetwork_internal_test.go +++ b/libnetwork/libnetwork_internal_test.go @@ -192,7 +192,6 @@ func TestEndpointMarshalling(t *testing.T) { name: "Bau", id: "efghijklmno", sandboxID: "ambarabaciccicocco", - anonymous: true, iface: &EndpointInterface{ mac: []byte{11, 12, 13, 14, 15, 16}, addr: &net.IPNet{ @@ -220,7 +219,7 @@ func TestEndpointMarshalling(t *testing.T) { t.Fatal(err) } - if e.name != ee.name || e.id != ee.id || e.sandboxID != ee.sandboxID || !reflect.DeepEqual(e.dnsNames, ee.dnsNames) || !compareEndpointInterface(e.iface, ee.iface) || e.anonymous != ee.anonymous { + if e.name != ee.name || e.id != ee.id || e.sandboxID != ee.sandboxID || !reflect.DeepEqual(e.dnsNames, ee.dnsNames) || !compareEndpointInterface(e.iface, ee.iface) { t.Fatalf("JSON marsh/unmarsh failed.\nOriginal:\n%#v\nDecoded:\n%#v\nOriginal iface: %#v\nDecodediface:\n%#v", e, ee, e.iface, ee.iface) } } diff --git a/libnetwork/network.go b/libnetwork/network.go index fced1c458f..91285bcc10 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -2162,10 +2162,6 @@ func (n *Network) createLoadBalancerSandbox() (retErr error) { CreateOptionIpam(n.loadBalancerIP, nil, nil, nil), CreateOptionLoadBalancer(), } - if n.hasLoadBalancerEndpoint() && !n.ingress { - // Mark LB endpoints as anonymous so they don't show up in DNS - epOptions = append(epOptions, CreateOptionAnonymous()) - } ep, err := n.createEndpoint(endpointName, epOptions...) if err != nil { return err From 13915f6521a5021d1d23b64c9831e4f4a6ef19a6 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Tue, 28 Nov 2023 12:11:37 +0100 Subject: [PATCH 10/10] libnet: document what Network.networkType represents Signed-off-by: Albin Kerouanton --- libnetwork/network.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnetwork/network.go b/libnetwork/network.go index 91285bcc10..a4aaf2f90b 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -175,7 +175,7 @@ func (i *IpamInfo) UnmarshalJSON(data []byte) error { type Network struct { ctrlr *Controller name string - networkType string + networkType string // networkType is the name of the netdriver used by this network id string created time.Time scope string // network data scope