github.com/opsramp/moby@v1.13.1/daemon/rename.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/Sirupsen/logrus"
     8  	dockercontainer "github.com/docker/docker/container"
     9  	"github.com/docker/libnetwork"
    10  )
    11  
    12  // ContainerRename changes the name of a container, using the oldName
    13  // to find the container. An error is returned if newName is already
    14  // reserved.
    15  func (daemon *Daemon) ContainerRename(oldName, newName string) error {
    16  	var (
    17  		sid string
    18  		sb  libnetwork.Sandbox
    19  	)
    20  
    21  	if oldName == "" || newName == "" {
    22  		return fmt.Errorf("Neither old nor new names may be empty")
    23  	}
    24  
    25  	if newName[0] != '/' {
    26  		newName = "/" + newName
    27  	}
    28  
    29  	container, err := daemon.GetContainer(oldName)
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	oldName = container.Name
    35  	oldIsAnonymousEndpoint := container.NetworkSettings.IsAnonymousEndpoint
    36  
    37  	if oldName == newName {
    38  		return fmt.Errorf("Renaming a container with the same name as its current name")
    39  	}
    40  
    41  	container.Lock()
    42  	defer container.Unlock()
    43  
    44  	links := map[string]*dockercontainer.Container{}
    45  	for k, v := range daemon.linkIndex.children(container) {
    46  		if !strings.HasPrefix(k, oldName) {
    47  			return fmt.Errorf("Linked container %s does not match parent %s", k, oldName)
    48  		}
    49  		links[strings.TrimPrefix(k, oldName)] = v
    50  	}
    51  
    52  	if newName, err = daemon.reserveName(container.ID, newName); err != nil {
    53  		return fmt.Errorf("Error when allocating new name: %v", err)
    54  	}
    55  
    56  	for k, v := range links {
    57  		daemon.nameIndex.Reserve(newName+k, v.ID)
    58  		daemon.linkIndex.link(container, v, newName+k)
    59  	}
    60  
    61  	container.Name = newName
    62  	container.NetworkSettings.IsAnonymousEndpoint = false
    63  
    64  	defer func() {
    65  		if err != nil {
    66  			container.Name = oldName
    67  			container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint
    68  			daemon.reserveName(container.ID, oldName)
    69  			for k, v := range links {
    70  				daemon.nameIndex.Reserve(oldName+k, v.ID)
    71  				daemon.linkIndex.link(container, v, oldName+k)
    72  				daemon.linkIndex.unlink(newName+k, v, container)
    73  				daemon.nameIndex.Release(newName + k)
    74  			}
    75  			daemon.releaseName(newName)
    76  		}
    77  	}()
    78  
    79  	for k, v := range links {
    80  		daemon.linkIndex.unlink(oldName+k, v, container)
    81  		daemon.nameIndex.Release(oldName + k)
    82  	}
    83  	daemon.releaseName(oldName)
    84  	if err = container.ToDisk(); err != nil {
    85  		return err
    86  	}
    87  
    88  	attributes := map[string]string{
    89  		"oldName": oldName,
    90  	}
    91  
    92  	if !container.Running {
    93  		daemon.LogContainerEventWithAttributes(container, "rename", attributes)
    94  		return nil
    95  	}
    96  
    97  	defer func() {
    98  		if err != nil {
    99  			container.Name = oldName
   100  			container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint
   101  			if e := container.ToDisk(); e != nil {
   102  				logrus.Errorf("%s: Failed in writing to Disk on rename failure: %v", container.ID, e)
   103  			}
   104  		}
   105  	}()
   106  
   107  	sid = container.NetworkSettings.SandboxID
   108  	if daemon.netController != nil {
   109  		sb, err = daemon.netController.SandboxByID(sid)
   110  		if err != nil {
   111  			return err
   112  		}
   113  
   114  		err = sb.Rename(strings.TrimPrefix(container.Name, "/"))
   115  		if err != nil {
   116  			return err
   117  		}
   118  	}
   119  
   120  	daemon.LogContainerEventWithAttributes(container, "rename", attributes)
   121  	return nil
   122  }