Browse Source

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 <albinker@gmail.com>
Albin Kerouanton 1 year ago
parent
commit
8b7af1d0f
2 changed files with 76 additions and 47 deletions
  1. 50 2
      daemon/rename.go
  2. 26 45
      libnetwork/endpoint.go

+ 50 - 2
daemon/rename.go

@@ -7,6 +7,7 @@ import (
 	"github.com/containerd/log"
 	"github.com/containerd/log"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/api/types/events"
 	dockercontainer "github.com/docker/docker/container"
 	dockercontainer "github.com/docker/docker/container"
+	"github.com/docker/docker/daemon/network"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/libnetwork"
 	"github.com/docker/docker/libnetwork"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
@@ -118,10 +119,57 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) (retErr error) {
 			return err
 			return err
 		}
 		}
 
 
-		err = sb.Rename(strings.TrimPrefix(container.Name, "/"))
-		if err != nil {
+		if err := sb.Rename(newName[1:]); err != nil {
 			return err
 			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)
 	daemon.LogContainerEventWithAttributes(container, events.ActionRename, attributes)

+ 26 - 45
libnetwork/endpoint.go

@@ -598,71 +598,52 @@ func (ep *Endpoint) sbJoin(sb *Sandbox, options ...EndpointOption) (err error) {
 }
 }
 
 
 func (ep *Endpoint) rename(name string) 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()
 	sb, ok := ep.getSandbox()
 	if !ok {
 	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
 		return nil
 	}
 	}
 
 
 	if c.isAgent() {
 	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)
 		}
 		}
-	} else {
-		n.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)
+		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)
 		}
 		}
-		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 {
 	} else {
-		n.updateSvcRecord(ep, true)
-		defer func() {
-			if err != nil {
-				n.updateSvcRecord(ep, false)
-				ep.name = oldName
-				ep.anonymous = oldAnonymous
-				n.updateSvcRecord(ep, true)
-			}
-		}()
+		nw.updateSvcRecord(ep, false)
+
+		ep.dnsNames = dnsNames
+		nw.updateSvcRecord(ep, true)
 	}
 	}
 
 
 	// Update the store with the updated name
 	// 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 err
+	return nil
 }
 }
 
 
 func (ep *Endpoint) hasInterface(iName string) bool {
 func (ep *Endpoint) hasInterface(iName string) bool {