github.com/raghuse92/packer@v1.3.2/common/step_http_server.go (about)

     1  package common
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"math/rand"
     8  	"net"
     9  	"net/http"
    10  
    11  	"github.com/hashicorp/packer/helper/common"
    12  	"github.com/hashicorp/packer/helper/multistep"
    13  	"github.com/hashicorp/packer/packer"
    14  )
    15  
    16  // This step creates and runs the HTTP server that is serving files from the
    17  // directory specified by the 'http_directory` configuration parameter in the
    18  // template.
    19  //
    20  // Uses:
    21  //   ui     packer.Ui
    22  //
    23  // Produces:
    24  //   http_port int - The port the HTTP server started on.
    25  type StepHTTPServer struct {
    26  	HTTPDir     string
    27  	HTTPPortMin uint
    28  	HTTPPortMax uint
    29  
    30  	l net.Listener
    31  }
    32  
    33  func (s *StepHTTPServer) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
    34  	ui := state.Get("ui").(packer.Ui)
    35  
    36  	var httpPort uint = 0
    37  	if s.HTTPDir == "" {
    38  		state.Put("http_port", httpPort)
    39  		return multistep.ActionContinue
    40  	}
    41  
    42  	// Find an available TCP port for our HTTP server
    43  	var httpAddr string
    44  	portRange := int(s.HTTPPortMax - s.HTTPPortMin)
    45  	for {
    46  		var err error
    47  		var offset uint = 0
    48  
    49  		if portRange > 0 {
    50  			// Intn will panic if portRange == 0, so we do a check.
    51  			// Intn is from [0, n), so add 1 to make from [0, n]
    52  			offset = uint(rand.Intn(portRange + 1))
    53  		}
    54  
    55  		httpPort = offset + s.HTTPPortMin
    56  		httpAddr = fmt.Sprintf("0.0.0.0:%d", httpPort)
    57  		log.Printf("Trying port: %d", httpPort)
    58  		s.l, err = net.Listen("tcp", httpAddr)
    59  		if err == nil {
    60  			break
    61  		}
    62  	}
    63  
    64  	ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
    65  
    66  	// Start the HTTP server and run it in the background
    67  	fileServer := http.FileServer(http.Dir(s.HTTPDir))
    68  	server := &http.Server{Addr: httpAddr, Handler: fileServer}
    69  	go server.Serve(s.l)
    70  
    71  	// Save the address into the state so it can be accessed in the future
    72  	state.Put("http_port", httpPort)
    73  	SetHTTPPort(fmt.Sprintf("%d", httpPort))
    74  
    75  	return multistep.ActionContinue
    76  }
    77  
    78  func SetHTTPPort(port string) error {
    79  	return common.SetSharedState("port", port, "")
    80  }
    81  
    82  func SetHTTPIP(ip string) error {
    83  	return common.SetSharedState("ip", ip, "")
    84  }
    85  
    86  func GetHTTPAddr() string {
    87  	ip, err := common.RetrieveSharedState("ip", "")
    88  	if err != nil {
    89  		return ""
    90  	}
    91  
    92  	port, err := common.RetrieveSharedState("port", "")
    93  	if err != nil {
    94  		return ""
    95  	}
    96  	return fmt.Sprintf("%s:%s", ip, port)
    97  }
    98  
    99  func (s *StepHTTPServer) Cleanup(multistep.StateBag) {
   100  	if s.l != nil {
   101  		// Close the listener so that the HTTP server stops
   102  		s.l.Close()
   103  	}
   104  	common.RemoveSharedStateFile("port", "")
   105  	common.RemoveSharedStateFile("ip", "")
   106  }