@@ -15,6 +15,7 @@ import (
1515 "regexp"
1616 "sort"
1717 "strconv"
18+ "strings"
1819 "sync"
1920 "sync/atomic"
2021 "time"
@@ -41,6 +42,7 @@ const (
4142 maxNumberOfPortsToCheck = 5
4243 portCheckingTimeout = 3 * time .Second
4344 unknownVersion = "unknown"
45+ wildcardIP = "0.0.0.0"
4446)
4547
4648// PortPool describes an available port range for clones.
@@ -73,11 +75,12 @@ type Provisioner struct {
7375 pm * pool.Manager
7476 networkID string
7577 instanceID string
78+ gateway string
7679}
7780
7881// New creates a new Provisioner instance.
7982func New (ctx context.Context , cfg * Config , dbCfg * resources.DB , docker * client.Client , pm * pool.Manager ,
80- instanceID , networkID string ) (* Provisioner , error ) {
83+ instanceID , networkID , gateway string ) (* Provisioner , error ) {
8184 if err := IsValidConfig (* cfg ); err != nil {
8285 return nil , errors .Wrap (err , "configuration is not valid" )
8386 }
@@ -93,6 +96,7 @@ func New(ctx context.Context, cfg *Config, dbCfg *resources.DB, docker *client.C
9396 pm : pm ,
9497 networkID : networkID ,
9598 instanceID : instanceID ,
99+ gateway : gateway ,
96100 ports : make ([]bool , cfg .PortPool .To - cfg .PortPool .From + 1 ),
97101 }
98102
@@ -435,7 +439,7 @@ func getLatestSnapshot(snapshots []resources.Snapshot) (*resources.Snapshot, err
435439func (p * Provisioner ) RevisePortPool () error {
436440 log .Msg (fmt .Sprintf ("Revising availability of the port range [%d - %d]" , p .config .PortPool .From , p .config .PortPool .To ))
437441
438- host , err := externalIP ( )
442+ host , err := hostIP ( p . gateway )
439443 if err != nil {
440444 return err
441445 }
@@ -468,13 +472,21 @@ func (p *Provisioner) RevisePortPool() error {
468472 return nil
469473}
470474
475+ func hostIP (gateway string ) (string , error ) {
476+ if gateway != "" {
477+ return gateway , nil
478+ }
479+
480+ return externalIP ()
481+ }
482+
471483// allocatePort tries to find a free port and occupy it.
472484func (p * Provisioner ) allocatePort () (uint , error ) {
473485 portOpts := p .config .PortPool
474486
475487 attempts := 0
476488
477- host , err := externalIP ( )
489+ host , err := hostIP ( p . gateway )
478490 if err != nil {
479491 return 0 , err
480492 }
@@ -598,6 +610,8 @@ func (p *Provisioner) stopPoolSessions(fsm pool.FSManager, exceptClones map[stri
598610}
599611
600612func (p * Provisioner ) getAppConfig (pool * resources.Pool , name string , port uint ) * resources.AppConfig {
613+ provisionHosts := p .getProvisionHosts ()
614+
601615 appConfig := & resources.AppConfig {
602616 CloneName : name ,
603617 DockerImage : p .config .DockerImage ,
@@ -607,12 +621,33 @@ func (p *Provisioner) getAppConfig(pool *resources.Pool, name string, port uint)
607621 Pool : pool ,
608622 ContainerConf : p .config .ContainerConfig ,
609623 NetworkID : p .networkID ,
610- ProvisionHosts : p . config . CloneAccessAddresses ,
624+ ProvisionHosts : provisionHosts ,
611625 }
612626
613627 return appConfig
614628}
615629
630+ // getProvisionHosts adds an internal Docker gateway to the hosts rule if the user restricts access to IP addresses.
631+ func (p * Provisioner ) getProvisionHosts () string {
632+ provisionHosts := p .config .CloneAccessAddresses
633+
634+ if provisionHosts == "" || provisionHosts == wildcardIP {
635+ return provisionHosts
636+ }
637+
638+ hostSet := []string {p .gateway }
639+
640+ for _ , hostIP := range strings .Split (provisionHosts , "," ) {
641+ if hostIP != p .gateway {
642+ hostSet = append (hostSet , hostIP )
643+ }
644+ }
645+
646+ provisionHosts = strings .Join (hostSet , "," )
647+
648+ return provisionHosts
649+ }
650+
616651// LastSessionActivity returns the time of the last session activity.
617652func (p * Provisioner ) LastSessionActivity (session * resources.Session , minimumTime time.Time ) (* time.Time , error ) {
618653 fsm , err := p .pm .GetFSManager (session .Pool )
0 commit comments