Repository: moby/moby
File: daemon/libnetwork/osl/namespace_linux.go (Go)

Code before:
// Key returns the path where the network namespace is mounted.
func (n *Namespace) Key() string {
	return n.path
}

// Destroy destroys the sandbox.
func (n *Namespace) Destroy() error {
	n.nlHandle.Handle.Close()
	// Assuming no running process is executing in this network namespace,
	// unmounting is sufficient to destroy it.
	if err := syscall.Unmount(n.path, syscall.MNT_DETACH); err != nil {
		return err
	}

	// Remove the path where the netns was mounted
	if err := os.Remove(n.path); err != nil {
		log.G(context.TODO()).WithError(err).Error("error removing namespace file")
	}
	return nil
}

// RestoreInterfaces restores the network namespace's interfaces and sends
// unsolicited ARP/NA messages to update neighbor caches.
func (n *Namespace) RestoreInterfaces(ctx context.Context, interfaces map[Iface][]IfaceOption) error {
	// restore interfaces
	for iface, opts := range interfaces {
		i, err := newInterface(n, iface.SrcName, iface.DstPrefix, iface.DstName, opts...)
		if err != nil {
			return err
		}
		if n.isDefault {
			i.dstName = i.srcName
		} else {
			links, err := n.nlHandle.LinkList()
			if err != nil {
				return fmt.Errorf("failed to retrieve list of links in network namespace %q during restore", n.path)
			}
			// due to the docker network connect/disconnect, so the dstName should
			// restore from the namespace
			for _, link := range links {
				ifaceName := link.Attrs().Name
				if i.dstPrefix == "vxlan" && strings.HasPrefix(ifaceName, "vxlan") {
					i.dstName = ifaceName
					break
				}
				// find the interface name by ip
				findIfname := func(needle *net.IPNet, haystack []netlink.Addr) (string, bool) {
					for _, addr := range haystack {
						if addr.IPNet.String() == needle.String() {
							return ifaceName, true
						}

Review comment (suggestion):
Just quick comment (but I haven't looked in-depth); as we're now passing through the context, we should also look if any context-cancellation should be handled.

Basically, the "promise" is if a function accepts a context, it should be context-aware; it's good to verify if it properly handles the context when adding it (as it's easy to forget revisiting that later 😅)

Code after:
// Key returns the path where the network namespace is mounted.
func (n *Namespace) Key() string {
	return n.path
}

// Destroy destroys the sandbox.
func (n *Namespace) Destroy() error {
	n.nlHandle.Handle.Close()
	// Assuming no running process is executing in this network namespace,
	// unmounting is sufficient to destroy it.
	if err := syscall.Unmount(n.path, syscall.MNT_DETACH); err != nil {
		return err
	}

	// Remove the path where the netns was mounted
	if err := os.Remove(n.path); err != nil {
		log.G(context.TODO()).WithError(err).Error("error removing namespace file")
	}
	return nil
}

// RestoreInterfaces restores the network namespace's interfaces and sends
// unsolicited ARP/NA messages to update neighbor caches.
func (n *Namespace) RestoreInterfaces(ctx context.Context, interfaces map[Iface][]IfaceOption) error {
	// restore interfaces
	for iface, opts := range interfaces {
		if err := ctx.Err(); err != nil {
			return err
		}
		i, err := newInterface(n, iface.SrcName, iface.DstPrefix, iface.DstName, opts...)
		if err != nil {
			return err
		}
		if n.isDefault {
			i.dstName = i.srcName
		} else {
			links, err := n.nlHandle.LinkList()
			if err != nil {
				return fmt.Errorf("failed to retrieve list of links in network namespace %q during restore", n.path)
			}
			// due to the docker network connect/disconnect, so the dstName should
			// restore from the namespace
			for _, link := range links {
				ifaceName := link.Attrs().Name
				if i.dstPrefix == "vxlan" && strings.HasPrefix(ifaceName, "vxlan") {
					i.dstName = ifaceName
					break
				}
				// find the interface name by ip
				findIfname := func(needle *net.IPNet, haystack []netlink.Addr) (string, bool) {
					for _, addr := range haystack {