github.com/moby/docker@v26.1.3+incompatible/daemon/names.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/containerd/log"
     9  	"github.com/docker/docker/container"
    10  	"github.com/docker/docker/daemon/names"
    11  	"github.com/docker/docker/errdefs"
    12  	"github.com/docker/docker/pkg/namesgenerator"
    13  	"github.com/docker/docker/pkg/stringid"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  var (
    18  	validContainerNameChars   = names.RestrictedNameChars
    19  	validContainerNamePattern = names.RestrictedNamePattern
    20  )
    21  
    22  func (daemon *Daemon) registerName(container *container.Container) error {
    23  	if daemon.Exists(container.ID) {
    24  		return fmt.Errorf("Container is already loaded")
    25  	}
    26  	if err := validateID(container.ID); err != nil {
    27  		return err
    28  	}
    29  	if container.Name == "" {
    30  		name, err := daemon.generateAndReserveName(container.ID)
    31  		if err != nil {
    32  			return err
    33  		}
    34  		container.Name = name
    35  		return nil
    36  	}
    37  	return daemon.containersReplica.ReserveName(container.Name, container.ID)
    38  }
    39  
    40  func (daemon *Daemon) generateIDAndName(name string) (string, string, error) {
    41  	var (
    42  		err error
    43  		id  = stringid.GenerateRandomID()
    44  	)
    45  
    46  	if name == "" {
    47  		if name, err = daemon.generateAndReserveName(id); err != nil {
    48  			return "", "", err
    49  		}
    50  		return id, name, nil
    51  	}
    52  
    53  	if name, err = daemon.reserveName(id, name); err != nil {
    54  		return "", "", err
    55  	}
    56  
    57  	return id, name, nil
    58  }
    59  
    60  func (daemon *Daemon) reserveName(id, name string) (string, error) {
    61  	if !validContainerNamePattern.MatchString(strings.TrimPrefix(name, "/")) {
    62  		return "", errdefs.InvalidParameter(errors.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars))
    63  	}
    64  	if name[0] != '/' {
    65  		name = "/" + name
    66  	}
    67  
    68  	if err := daemon.containersReplica.ReserveName(name, id); err != nil {
    69  		if errors.Is(err, container.ErrNameReserved) {
    70  			id, err := daemon.containersReplica.Snapshot().GetID(name)
    71  			if err != nil {
    72  				log.G(context.TODO()).Errorf("got unexpected error while looking up reserved name: %v", err)
    73  				return "", err
    74  			}
    75  			return "", nameConflictError{id: id, name: name}
    76  		}
    77  		return "", errors.Wrapf(err, "error reserving name: %q", name)
    78  	}
    79  	return name, nil
    80  }
    81  
    82  func (daemon *Daemon) releaseName(name string) {
    83  	daemon.containersReplica.ReleaseName(name)
    84  }
    85  
    86  func (daemon *Daemon) generateAndReserveName(id string) (string, error) {
    87  	var name string
    88  	for i := 0; i < 6; i++ {
    89  		name = namesgenerator.GetRandomName(i)
    90  		if name[0] != '/' {
    91  			name = "/" + name
    92  		}
    93  
    94  		if err := daemon.containersReplica.ReserveName(name, id); err != nil {
    95  			if errors.Is(err, container.ErrNameReserved) {
    96  				continue
    97  			}
    98  			return "", err
    99  		}
   100  		return name, nil
   101  	}
   102  
   103  	name = "/" + stringid.TruncateID(id)
   104  	if err := daemon.containersReplica.ReserveName(name, id); err != nil {
   105  		return "", err
   106  	}
   107  	return name, nil
   108  }
   109  
   110  func validateID(id string) error {
   111  	if id == "" {
   112  		return fmt.Errorf("Invalid empty id")
   113  	}
   114  	return nil
   115  }