@@ -84,6 +84,7 @@ func New(ctx context.Context, cfg *Config, dbCfg *resources.DB, docker *client.C
8484 portChecker : & localPortChecker {},
8585 pm : pm ,
8686 networkID : networkID ,
87+ ports : make ([]bool , cfg .PortPool .To - cfg .PortPool .From ),
8788 }
8889
8990 return p , nil
@@ -114,8 +115,8 @@ func isValidConfigModeLocal(config Config) error {
114115
115116// Init inits provision.
116117func (p * Provisioner ) Init () error {
117- if err := p .initPortPool (); err != nil {
118- return errors .Wrap (err , "failed to init port pool" )
118+ if err := p .RevisePortPool (); err != nil {
119+ return errors .Wrap (err , "failed to revise port pool" )
119120 }
120121
121122 imageExists , err := docker .ImageExists (p .runner , p .config .DockerImage )
@@ -408,20 +409,21 @@ func (p *Provisioner) getSnapshot(snapshotID string) (*resources.Snapshot, error
408409 return & snapshots [0 ], nil
409410}
410411
411- func (p * Provisioner ) initPortPool () error {
412- portOpts := p .config .PortPool
413- size := portOpts .To - portOpts .From
414- p .ports = make ([]bool , size )
415-
416- log .Msg (fmt .Sprintf ("checking availability of the port range [%d - %d]" , portOpts .From , portOpts .To ))
412+ // RevisePortPool checks and aligns availability of the port range.
413+ func (p * Provisioner ) RevisePortPool () error {
414+ log .Msg (fmt .Sprintf ("Revising availability of the port range [%d - %d]" , p .config .PortPool .From , p .config .PortPool .To ))
417415
418416 host , err := externalIP ()
419417 if err != nil {
420418 return err
421419 }
422420
421+ p .mu .Lock ()
422+ defer p .mu .Unlock ()
423+
423424 availablePorts := 0
424- for port := portOpts .From ; port < portOpts .To ; port ++ {
425+
426+ for port := p .config .PortPool .From ; port < p .config .PortPool .To ; port ++ {
425427 if err := p .portChecker .checkPortAvailability (host , port ); err != nil {
426428 log .Msg (fmt .Sprintf ("port %d is not available, marking as busy" , port ))
427429
@@ -431,11 +433,12 @@ func (p *Provisioner) initPortPool() error {
431433
432434 continue
433435 }
434- availablePorts ++
435- }
436436
437- if availablePorts == 0 {
438- return NewNoRoomError ("no available ports" )
437+ if err := p .setPortStatus (port , false ); err != nil {
438+ log .Err (fmt .Sprintf ("cannot free port %d: %s" , port , err ))
439+ }
440+
441+ availablePorts ++
439442 }
440443
441444 log .Msg (availablePorts , " ports are available" )
0 commit comments