github.com/Hashicorp/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 }