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