@@ -18,6 +18,7 @@ package dockercontroller
1818
1919import (
2020 "bytes"
21+ "encoding/hex"
2122 "fmt"
2223 "io"
2324 "strings"
@@ -29,6 +30,7 @@ import (
2930
3031 "github.com/fsouza/go-dockerclient"
3132 "github.com/hyperledger/fabric/common/flogging"
33+ "github.com/hyperledger/fabric/common/util"
3234 container "github.com/hyperledger/fabric/core/container/api"
3335 "github.com/hyperledger/fabric/core/container/ccintf"
3436 cutil "github.com/hyperledger/fabric/core/container/util"
@@ -40,6 +42,8 @@ import (
4042var (
4143 dockerLogger = flogging .MustGetLogger ("dockercontroller" )
4244 hostConfig * docker.HostConfig
45+ vmRegExp = regexp .MustCompile ("[^a-zA-Z0-9-_.]" )
46+ imageRegExp = regexp .MustCompile ("^[a-z0-9]+(([._-][a-z0-9]+)+)?$" )
4347)
4448
4549// getClient returns an instance that implements dockerClient interface
@@ -163,7 +167,7 @@ func (vm *DockerVM) createContainer(ctxt context.Context, client dockerClient,
163167
164168func (vm * DockerVM ) deployImage (client dockerClient , ccid ccintf.CCID ,
165169 args []string , env []string , reader io.Reader ) error {
166- id , err := vm .GetVMName (ccid )
170+ id , err := vm .GetVMName (ccid , formatImageName )
167171 if err != nil {
168172 return err
169173 }
@@ -208,7 +212,7 @@ func (vm *DockerVM) Deploy(ctxt context.Context, ccid ccintf.CCID,
208212//Start starts a container using a previously created docker image
209213func (vm * DockerVM ) Start (ctxt context.Context , ccid ccintf.CCID ,
210214 args []string , env []string , builder container.BuildSpecFactory , prelaunchFunc container.PrelaunchFunc ) error {
211- imageID , err := vm .GetVMName (ccid )
215+ imageID , err := vm .GetVMName (ccid , formatImageName )
212216 if err != nil {
213217 return err
214218 }
@@ -219,7 +223,11 @@ func (vm *DockerVM) Start(ctxt context.Context, ccid ccintf.CCID,
219223 return err
220224 }
221225
222- containerID := strings .Replace (imageID , ":" , "_" , - 1 )
226+ containerID , err := vm .GetVMName (ccid , nil )
227+ if err != nil {
228+ return err
229+ }
230+
223231 attachStdout := viper .GetBool ("vm.docker.attachStdout" )
224232
225233 //stop,force remove if necessary
@@ -349,7 +357,7 @@ func (vm *DockerVM) Start(ctxt context.Context, ccid ccintf.CCID,
349357
350358//Stop stops a running chaincode
351359func (vm * DockerVM ) Stop (ctxt context.Context , ccid ccintf.CCID , timeout uint , dontkill bool , dontremove bool ) error {
352- id , err := vm .GetVMName (ccid )
360+ id , err := vm .GetVMName (ccid , nil )
353361 if err != nil {
354362 return err
355363 }
@@ -395,7 +403,7 @@ func (vm *DockerVM) stopInternal(ctxt context.Context, client dockerClient,
395403
396404//Destroy destroys an image
397405func (vm * DockerVM ) Destroy (ctxt context.Context , ccid ccintf.CCID , force bool , noprune bool ) error {
398- id , err := vm .GetVMName (ccid )
406+ id , err := vm .GetVMName (ccid , formatImageName )
399407 if err != nil {
400408 return err
401409 }
@@ -418,34 +426,48 @@ func (vm *DockerVM) Destroy(ctxt context.Context, ccid ccintf.CCID, force bool,
418426 return err
419427}
420428
421- //GetVMName generates the docker image from peer information given the hashcode. This is needed to
422- //keep image name's unique in a single host, multi-peer environment (such as a development environment)
423- func (vm * DockerVM ) GetVMName (ccid ccintf.CCID ) (string , error ) {
429+ // GetVMName generates the VM name from peer information. It accepts a format
430+ // function parameter to allow different formatting based on the desired use of
431+ // the name.
432+ func (vm * DockerVM ) GetVMName (ccid ccintf.CCID , format func (string ) (string , error )) (string , error ) {
424433 name := ccid .GetName ()
425434
426- //Convert to lowercase and replace any invalid characters with "-"
427- r := regexp .MustCompile ("[^a-zA-Z0-9-_.]" )
428-
435+ // replace any invalid characters with "-"
429436 if ccid .NetworkID != "" && ccid .PeerID != "" {
430- name = strings .ToLower (
431- r .ReplaceAllString (
432- fmt .Sprintf ("%s-%s-%s" , ccid .NetworkID , ccid .PeerID , name ), "-" ))
437+ name = vmRegExp .ReplaceAllString (
438+ fmt .Sprintf ("%s-%s-%s" , ccid .NetworkID , ccid .PeerID , name ), "-" )
433439 } else if ccid .NetworkID != "" {
434- name = strings .ToLower (
435- r .ReplaceAllString (
436- fmt .Sprintf ("%s-%s" , ccid .NetworkID , name ), "-" ))
440+ name = vmRegExp .ReplaceAllString (
441+ fmt .Sprintf ("%s-%s" , ccid .NetworkID , name ), "-" )
437442 } else if ccid .PeerID != "" {
438- name = strings .ToLower (
439- r .ReplaceAllString (
440- fmt .Sprintf ("%s-%s" , ccid .PeerID , name ), "-" ))
443+ name = vmRegExp .ReplaceAllString (
444+ fmt .Sprintf ("%s-%s" , ccid .PeerID , name ), "-" )
441445 }
442446
443- // Check name complies with Docker's repository naming rules
444- r = regexp .MustCompile ("^[a-z0-9]+(([._-][a-z0-9]+)+)?$" )
447+ if format != nil {
448+ formattedName , err := format (name )
449+ if err != nil {
450+ return formattedName , err
451+ }
452+ // check to ensure format function didn't add any invalid characters
453+ name = vmRegExp .ReplaceAllString (formattedName , "-" )
454+ }
455+ return name , nil
456+ }
445457
446- if ! r .MatchString (name ) {
458+ // formatImageName formats the docker image from peer information. This is
459+ // needed to keep image (repository) names unique in a single host, multi-peer
460+ // environment (such as a development environment). It computes the hash for the
461+ // supplied image name and then appends it to the lowercase image name to ensure
462+ // uniqueness.
463+ func formatImageName (name string ) (string , error ) {
464+ imageName := strings .ToLower (fmt .Sprintf ("%s-%s" , name , hex .EncodeToString (util .ComputeSHA256 ([]byte (name )))))
465+
466+ // Check that name complies with Docker's repository naming rules
467+ if ! imageRegExp .MatchString (imageName ) {
447468 dockerLogger .Errorf ("Error constructing Docker VM Name. '%s' breaks Docker's repository naming rules" , name )
448- return name , fmt .Errorf ("Error constructing Docker VM Name. '%s' breaks Docker's repository naming rules" , name )
469+ return imageName , fmt .Errorf ("Error constructing Docker VM Name. '%s' breaks Docker's repository naming rules" , imageName )
449470 }
450- return name , nil
471+
472+ return imageName , nil
451473}
0 commit comments