github.com/alouche/packer@v0.3.7/builder/virtualbox/step_http_server.go (about)

     1  package virtualbox
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/multistep"
     6  	"github.com/mitchellh/packer/packer"
     7  	"log"
     8  	"math/rand"
     9  	"net"
    10  	"net/http"
    11  )
    12  
    13  // This step creates and runs the HTTP server that is serving the files
    14  // specified by the 'http_files` configuration parameter in the template.
    15  //
    16  // Uses:
    17  //   config *config
    18  //   ui     packer.Ui
    19  //
    20  // Produces:
    21  //   http_port int - The port the HTTP server started on.
    22  type stepHTTPServer struct {
    23  	l net.Listener
    24  }
    25  
    26  func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
    27  	config := state.Get("config").(*config)
    28  	ui := state.Get("ui").(packer.Ui)
    29  
    30  	var httpPort uint = 0
    31  	if config.HTTPDir == "" {
    32  		state.Put("http_port", httpPort)
    33  		return multistep.ActionContinue
    34  	}
    35  
    36  	// Find an available TCP port for our HTTP server
    37  	var httpAddr string
    38  	portRange := int(config.HTTPPortMax - config.HTTPPortMin)
    39  	for {
    40  		var err error
    41  		var offset uint = 0
    42  
    43  		if portRange > 0 {
    44  			// Intn will panic if portRange == 0, so we do a check.
    45  			offset = uint(rand.Intn(portRange))
    46  		}
    47  
    48  		httpPort = offset + config.HTTPPortMin
    49  		httpAddr = fmt.Sprintf(":%d", httpPort)
    50  		log.Printf("Trying port: %d", httpPort)
    51  		s.l, err = net.Listen("tcp", httpAddr)
    52  		if err == nil {
    53  			break
    54  		}
    55  	}
    56  
    57  	ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
    58  
    59  	// Start the HTTP server and run it in the background
    60  	fileServer := http.FileServer(http.Dir(config.HTTPDir))
    61  	server := &http.Server{Addr: httpAddr, Handler: fileServer}
    62  	go server.Serve(s.l)
    63  
    64  	// Save the address into the state so it can be accessed in the future
    65  	state.Put("http_port", httpPort)
    66  
    67  	return multistep.ActionContinue
    68  }
    69  
    70  func (s *stepHTTPServer) Cleanup(multistep.StateBag) {
    71  	if s.l != nil {
    72  		// Close the listener so that the HTTP server stops
    73  		s.l.Close()
    74  	}
    75  }