2016-05-24 11:49:26 -04:00
package daemon
import (
"fmt"
2016-11-23 14:45:35 -05:00
"strings"
2016-05-24 11:49:26 -04:00
2016-12-21 16:42:47 -05:00
"github.com/docker/docker/api"
2016-05-24 11:49:26 -04:00
"github.com/docker/docker/container"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/docker/docker/pkg/stringid"
2017-07-19 10:20:13 -04:00
"github.com/pkg/errors"
2017-07-26 17:42:13 -04:00
"github.com/sirupsen/logrus"
2016-05-24 11:49:26 -04:00
)
var (
2016-12-21 16:42:47 -05:00
validContainerNameChars = api . RestrictedNameChars
validContainerNamePattern = api . RestrictedNamePattern
2016-05-24 11:49:26 -04:00
)
func ( daemon * Daemon ) registerName ( container * container . Container ) error {
if daemon . Exists ( container . ID ) {
return fmt . Errorf ( "Container is already loaded" )
}
if err := validateID ( container . ID ) ; err != nil {
return err
}
if container . Name == "" {
name , err := daemon . generateNewName ( container . ID )
if err != nil {
return err
}
container . Name = name
}
2017-06-29 21:56:22 -04:00
return daemon . containersReplica . ReserveName ( container . Name , container . ID )
2016-05-24 11:49:26 -04:00
}
func ( daemon * Daemon ) generateIDAndName ( name string ) ( string , string , error ) {
var (
err error
id = stringid . GenerateNonCryptoID ( )
)
if name == "" {
if name , err = daemon . generateNewName ( id ) ; err != nil {
return "" , "" , err
}
return id , name , nil
}
if name , err = daemon . reserveName ( id , name ) ; err != nil {
return "" , "" , err
}
return id , name , nil
}
func ( daemon * Daemon ) reserveName ( id , name string ) ( string , error ) {
2016-11-23 14:45:35 -05:00
if ! validContainerNamePattern . MatchString ( strings . TrimPrefix ( name , "/" ) ) {
2017-07-19 10:20:13 -04:00
return "" , validationError { errors . Errorf ( "Invalid container name (%s), only %s are allowed" , name , validContainerNameChars ) }
2016-05-24 11:49:26 -04:00
}
if name [ 0 ] != '/' {
name = "/" + name
}
2017-06-29 21:56:22 -04:00
if err := daemon . containersReplica . ReserveName ( name , id ) ; err != nil {
if err == container . ErrNameReserved {
id , err := daemon . containersReplica . Snapshot ( ) . GetID ( name )
2016-05-24 11:49:26 -04:00
if err != nil {
logrus . Errorf ( "got unexpected error while looking up reserved name: %v" , err )
return "" , err
}
2017-07-19 10:20:13 -04:00
return "" , validationError { errors . Errorf ( "Conflict. The container name %q is already in use by container %q. You have to remove (or rename) that container to be able to reuse that name." , name , id ) }
2016-05-24 11:49:26 -04:00
}
2017-07-19 10:20:13 -04:00
return "" , errors . Wrapf ( err , "error reserving name: %q" , name )
2016-05-24 11:49:26 -04:00
}
return name , nil
}
func ( daemon * Daemon ) releaseName ( name string ) {
2017-06-29 21:56:22 -04:00
daemon . containersReplica . ReleaseName ( name )
2016-05-24 11:49:26 -04:00
}
func ( daemon * Daemon ) generateNewName ( id string ) ( string , error ) {
var name string
for i := 0 ; i < 6 ; i ++ {
name = namesgenerator . GetRandomName ( i )
if name [ 0 ] != '/' {
name = "/" + name
}
2017-06-29 21:56:22 -04:00
if err := daemon . containersReplica . ReserveName ( name , id ) ; err != nil {
if err == container . ErrNameReserved {
2016-05-24 11:49:26 -04:00
continue
}
return "" , err
}
return name , nil
}
name = "/" + stringid . TruncateID ( id )
2017-06-29 21:56:22 -04:00
if err := daemon . containersReplica . ReserveName ( name , id ) ; err != nil {
2016-05-24 11:49:26 -04:00
return "" , err
}
return name , nil
}
2016-05-27 05:32:26 -04:00
func validateID ( id string ) error {
if id == "" {
return fmt . Errorf ( "Invalid empty id" )
}
return nil
}