From 1685a1c4c0c53c56c3d1c49c1c33c1f1e5b20b9f Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Fri, 15 Mar 2019 16:23:42 +0100 Subject: [PATCH 01/20] add common/net package that can listen on a random port in a range --- common/net/configure_port.go | 104 +++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 common/net/configure_port.go diff --git a/common/net/configure_port.go b/common/net/configure_port.go new file mode 100644 index 000000000..cb1fe66bf --- /dev/null +++ b/common/net/configure_port.go @@ -0,0 +1,104 @@ +package net + +import ( + "context" + "errors" + "fmt" + "log" + "math/rand" + "net" + "strconv" + + "github.com/gofrs/flock" + + "github.com/hashicorp/packer/packer" +) + +var _ net.Listener = &Listener{} + +// Listener wraps a net.Lister with some magic packer capabilies. For example +// until you call Listener.Close, any call to ListenRangeConfig.Listen cannot +// bind to Port. Packer tries tells moving parts which port they can use, but +// often the port has to be released before a 3rd party is started, like a VNC +// server. +type Listener struct { + // Listener can be closed but Port will be file locked by packer until + // Close is called. + net.Listener + Port int + Address string + lock *flock.Flock +} + +func (l *Listener) Close() error { + err := l.lock.Unlock() + if err != nil { + log.Printf("cannot unlock lockfile %#v: %v", l, err) + } + return l.Listener.Close() +} + +// ListenRangeConfig contains options for listening to a free address [Min,Max) +// range. ListenRangeConfig wraps a net.ListenConfig. +type ListenRangeConfig struct { + // tcp", "udp" + Network string + Addr string + Min, Max int + net.ListenConfig +} + +// Listen tries to Listen to a random open TCP port in the [min, max) range +// until ctx is cancelled. +// Listen uses net.ListenConfig.Listen internally. +func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { + if lc.Max < lc.Min { + lc.Min, lc.Max = lc.Max, lc.Min + } + portRange := int(lc.Max - lc.Min) + if portRange == 0 { + // Intn will panic if portRange == 0 + return nil, errors.New("ListenRandomPort: port range is zero") + } + for { + if err := ctx.Err(); err != nil { + return nil, err + } + + port := rand.Intn(portRange) + lc.Min + + lockFilePath, err := packer.CachePath("port", strconv.Itoa(port)) + if err != nil { + return nil, err + } + + lock := flock.New(lockFilePath) + locked, err := lock.TryLock() + if err != nil { + return nil, err + } + if !locked { + continue // this port seems to be locked by another packer goroutine + } + + log.Printf("Trying port: %d", port) + + l, err := lc.ListenConfig.Listen(ctx, lc.Network, fmt.Sprintf("%s:%d", lc.Addr, port)) + if err != nil { + if err := lock.Unlock(); err != nil { + log.Printf("Could not unlock file lock for port %d: %v", port, err) + } + + continue // this port is most likely already open + } + + log.Printf("Found available port: %d on IP: %s", port, lc.Addr) + return &Listener{ + Address: lc.Addr, + Port: port, + Listener: l, + lock: lock, + }, err + + } +} From 6df412851718a3eca77b872f098c553ac073f52b Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Fri, 15 Mar 2019 16:25:45 +0100 Subject: [PATCH 02/20] StepHTTPServer: use the common/net pkg --- common/http_config.go | 4 ++-- common/step_http_server.go | 48 +++++++++++++++----------------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/common/http_config.go b/common/http_config.go index bb9b46b26..8a6809ac4 100644 --- a/common/http_config.go +++ b/common/http_config.go @@ -9,8 +9,8 @@ import ( // HTTPConfig contains configuration for the local HTTP Server type HTTPConfig struct { HTTPDir string `mapstructure:"http_directory"` - HTTPPortMin uint `mapstructure:"http_port_min"` - HTTPPortMax uint `mapstructure:"http_port_max"` + HTTPPortMin int `mapstructure:"http_port_min"` + HTTPPortMax int `mapstructure:"http_port_max"` } func (c *HTTPConfig) Prepare(ctx *interpolate.Context) []error { diff --git a/common/step_http_server.go b/common/step_http_server.go index 8e9e58983..e8cd1c6ca 100644 --- a/common/step_http_server.go +++ b/common/step_http_server.go @@ -3,11 +3,10 @@ package common import ( "context" "fmt" - "log" - "math/rand" - "net" + "net/http" + "github.com/hashicorp/packer/common/net" "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -24,44 +23,35 @@ import ( // http_port int - The port the HTTP server started on. type StepHTTPServer struct { HTTPDir string - HTTPPortMin uint - HTTPPortMax uint + HTTPPortMin int + HTTPPortMax int - l net.Listener + l *net.Listener } -func (s *StepHTTPServer) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { +func (s *StepHTTPServer) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) - var httpPort uint = 0 if s.HTTPDir == "" { - state.Put("http_port", httpPort) + state.Put("http_port", uint(0)) return multistep.ActionContinue } // Find an available TCP port for our HTTP server var httpAddr string - portRange := int(s.HTTPPortMax - s.HTTPPortMin) - for { - var err error - var offset uint = 0 + var err error + s.l, err = net.ListenRangeConfig{ + Min: s.HTTPPortMin, + Max: s.HTTPPortMax, + Addr: "0.0.0.0", + Network: "tcp", + }.Listen(ctx) - if portRange > 0 { - // Intn will panic if portRange == 0, so we do a check. - // Intn is from [0, n), so add 1 to make from [0, n] - offset = uint(rand.Intn(portRange + 1)) - } - - httpPort = offset + s.HTTPPortMin - httpAddr = fmt.Sprintf("0.0.0.0:%d", httpPort) - log.Printf("Trying port: %d", httpPort) - s.l, err = net.Listen("tcp", httpAddr) - if err == nil { - break - } + if err != nil { + return multistep.ActionHalt } - ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort)) + ui.Say(fmt.Sprintf("Starting HTTP server on port %d", s.l.Port)) // Start the HTTP server and run it in the background fileServer := http.FileServer(http.Dir(s.HTTPDir)) @@ -69,8 +59,8 @@ func (s *StepHTTPServer) Run(_ context.Context, state multistep.StateBag) multis go server.Serve(s.l) // Save the address into the state so it can be accessed in the future - state.Put("http_port", httpPort) - SetHTTPPort(fmt.Sprintf("%d", httpPort)) + state.Put("http_port", s.l.Port) + SetHTTPPort(fmt.Sprintf("%d", s.l.Port)) return multistep.ActionContinue } From b5d78d47f540fe10899195bb578b5c50671f2dba Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Fri, 15 Mar 2019 16:37:44 +0100 Subject: [PATCH 03/20] vmware StepConfigureVNC: use common/net pkg to find open port --- builder/vmware/common/run_config.go | 4 +- builder/vmware/common/step_configure_vnc.go | 62 ++++++++------------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/builder/vmware/common/run_config.go b/builder/vmware/common/run_config.go index c4bfc3413..e8b6a3d37 100644 --- a/builder/vmware/common/run_config.go +++ b/builder/vmware/common/run_config.go @@ -10,8 +10,8 @@ type RunConfig struct { Headless bool `mapstructure:"headless"` VNCBindAddress string `mapstructure:"vnc_bind_address"` - VNCPortMin uint `mapstructure:"vnc_port_min"` - VNCPortMax uint `mapstructure:"vnc_port_max"` + VNCPortMin int `mapstructure:"vnc_port_min"` + VNCPortMax int `mapstructure:"vnc_port_max"` VNCDisablePassword bool `mapstructure:"vnc_disable_password"` } diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index 54f5ac182..284c58edd 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -5,8 +5,8 @@ import ( "fmt" "log" "math/rand" - "net" + "github.com/hashicorp/packer/common/net" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -18,43 +18,20 @@ import ( // vmx_path string // // Produces: -// vnc_port uint - The port that VNC is configured to listen on. +// vnc_port int - The port that VNC is configured to listen on. type StepConfigureVNC struct { Enabled bool VNCBindAddress string - VNCPortMin uint - VNCPortMax uint + VNCPortMin int + VNCPortMax int VNCDisablePassword bool + + l *net.Listener } type VNCAddressFinder interface { - VNCAddress(string, uint, uint) (string, uint, error) - // UpdateVMX, sets driver specific VNC values to VMX data. - UpdateVMX(vncAddress, vncPassword string, vncPort uint, vmxData map[string]string) -} - -func (StepConfigureVNC) VNCAddress(vncBindAddress string, portMin, portMax uint) (string, uint, error) { - // Find an open VNC port. Note that this can still fail later on - // because we have to release the port at some point. But this does its - // best. - var vncPort uint - portRange := int(portMax - portMin) - for { - if portRange > 0 { - vncPort = uint(rand.Intn(portRange)) + portMin - } else { - vncPort = portMin - } - - log.Printf("Trying port: %d", vncPort) - l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", vncBindAddress, vncPort)) - if err == nil { - defer l.Close() - break - } - } - return vncBindAddress, vncPort, nil + UpdateVMX(vncAddress, vncPassword string, vncPort int, vmxData map[string]string) } func VNCPassword(skipPassword bool) string { @@ -75,7 +52,7 @@ func VNCPassword(skipPassword bool) string { return string(password) } -func (s *StepConfigureVNC) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { +func (s *StepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { if !s.Enabled { log.Println("Skipping VNC configuration step...") return multistep.ActionContinue @@ -99,19 +76,27 @@ func (s *StepConfigureVNC) Run(_ context.Context, state multistep.StateBag) mult } else { vncFinder = s } + log.Printf("Looking for available port between %d and %d", s.VNCPortMin, s.VNCPortMax) - vncBindAddress, vncPort, err := vncFinder.VNCAddress(s.VNCBindAddress, s.VNCPortMin, s.VNCPortMax) + s.l, err = net.ListenRangeConfig{ + Addr: s.VNCBindAddress, + Min: s.VNCPortMin, + Max: s.VNCPortMax, + Network: "tcp", + }.Listen(ctx) + if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } + s.l.Listener.Close() // free port, but don't unlock lock file vncPassword := VNCPassword(s.VNCDisablePassword) - log.Printf("Found available VNC port: %d", vncPort) + log.Printf("Found available VNC port: %v", s.l) - vncFinder.UpdateVMX(vncBindAddress, vncPassword, vncPort, vmxData) + vncFinder.UpdateVMX(s.l.Address, vncPassword, s.l.Port, vmxData) if err := WriteVMX(vmxPath, vmxData); err != nil { err := fmt.Errorf("Error writing VMX data: %s", err) @@ -120,14 +105,12 @@ func (s *StepConfigureVNC) Run(_ context.Context, state multistep.StateBag) mult return multistep.ActionHalt } - state.Put("vnc_port", vncPort) - state.Put("vnc_ip", vncBindAddress) state.Put("vnc_password", vncPassword) return multistep.ActionContinue } -func (StepConfigureVNC) UpdateVMX(address, password string, port uint, data map[string]string) { +func (*StepConfigureVNC) UpdateVMX(address, password string, port int, data map[string]string) { data["remotedisplay.vnc.enabled"] = "TRUE" data["remotedisplay.vnc.port"] = fmt.Sprintf("%d", port) data["remotedisplay.vnc.ip"] = address @@ -136,5 +119,8 @@ func (StepConfigureVNC) UpdateVMX(address, password string, port uint, data map[ } } -func (StepConfigureVNC) Cleanup(multistep.StateBag) { +func (s *StepConfigureVNC) Cleanup(multistep.StateBag) { + if err := s.l.Close(); err != nil { + log.Printf("failed to unlock port lockfile: %v", err) + } } From 59370986fba8508bdc163f4b3c65f1f5ced9887b Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Fri, 15 Mar 2019 16:51:23 +0100 Subject: [PATCH 04/20] virtualbox StepForwardSSH: use common/net pkg to find open port --- builder/virtualbox/common/ssh_config.go | 4 +- builder/virtualbox/common/step_forward_ssh.go | 49 +++++++++++-------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/builder/virtualbox/common/ssh_config.go b/builder/virtualbox/common/ssh_config.go index 3136bca98..10159cc86 100644 --- a/builder/virtualbox/common/ssh_config.go +++ b/builder/virtualbox/common/ssh_config.go @@ -11,8 +11,8 @@ import ( type SSHConfig struct { Comm communicator.Config `mapstructure:",squash"` - SSHHostPortMin uint `mapstructure:"ssh_host_port_min"` - SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` + SSHHostPortMin int `mapstructure:"ssh_host_port_min"` + SSHHostPortMax int `mapstructure:"ssh_host_port_max"` SSHSkipNatMapping bool `mapstructure:"ssh_skip_nat_mapping"` // These are deprecated, but we keep them around for BC diff --git a/builder/virtualbox/common/step_forward_ssh.go b/builder/virtualbox/common/step_forward_ssh.go index b4e3b2f25..345b9c55f 100644 --- a/builder/virtualbox/common/step_forward_ssh.go +++ b/builder/virtualbox/common/step_forward_ssh.go @@ -4,9 +4,8 @@ import ( "context" "fmt" "log" - "math/rand" - "net" + "github.com/hashicorp/packer/common/net" "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -23,12 +22,14 @@ import ( // Produces: type StepForwardSSH struct { CommConfig *communicator.Config - HostPortMin uint - HostPortMax uint + HostPortMin int + HostPortMax int SkipNatMapping bool + + l *net.Listener } -func (s *StepForwardSSH) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { +func (s *StepForwardSSH) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) @@ -45,22 +46,21 @@ func (s *StepForwardSSH) Run(_ context.Context, state multistep.StateBag) multis log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", s.HostPortMin, s.HostPortMax) - portRange := int(s.HostPortMax - s.HostPortMin + 1) - offset := rand.Intn(portRange) - - for { - sshHostPort = offset + int(s.HostPortMin) - log.Printf("Trying port: %d", sshHostPort) - l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", sshHostPort)) - if err == nil { - defer l.Close() - break - } - offset++ - if offset == portRange { - offset = 0 - } + var err error + s.l, err = net.ListenRangeConfig{ + Addr: "127.0.0.1", + Min: s.HostPortMin, + Max: s.HostPortMax, + Network: "tcp", + }.Listen(ctx) + if err != nil { + err := fmt.Errorf("Error creating port forwarding rule: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } + s.l.Listener.Close() // free port, but don't unlock lock file + sshHostPort = s.l.Port // Create a forwarded port mapping to the VM ui.Say(fmt.Sprintf("Creating forwarded port mapping for communicator (SSH, WinRM, etc) (host port %d)", sshHostPort)) @@ -83,4 +83,11 @@ func (s *StepForwardSSH) Run(_ context.Context, state multistep.StateBag) multis return multistep.ActionContinue } -func (s *StepForwardSSH) Cleanup(state multistep.StateBag) {} +func (s *StepForwardSSH) Cleanup(state multistep.StateBag) { + if s.l != nil { + err := s.l.Close() + if err != nil { + log.Printf("failed to unlock port lockfile: %v", err) + } + } +} From f67b5ff59dc1fa6c95ecfc1a092cf0b37bf72676 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 13:24:59 +0100 Subject: [PATCH 05/20] virtualbox StepConfigureVRDP: use common/net pkg to find open port --- builder/virtualbox/common/run_config.go | 4 +- .../virtualbox/common/step_configure_vrdp.go | 50 +++++++++++-------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/builder/virtualbox/common/run_config.go b/builder/virtualbox/common/run_config.go index cf94c306b..e5cae02a6 100644 --- a/builder/virtualbox/common/run_config.go +++ b/builder/virtualbox/common/run_config.go @@ -10,8 +10,8 @@ type RunConfig struct { Headless bool `mapstructure:"headless"` VRDPBindAddress string `mapstructure:"vrdp_bind_address"` - VRDPPortMin uint `mapstructure:"vrdp_port_min"` - VRDPPortMax uint `mapstructure:"vrdp_port_max"` + VRDPPortMin int `mapstructure:"vrdp_port_min"` + VRDPPortMax int `mapstructure:"vrdp_port_max"` } func (c *RunConfig) Prepare(ctx *interpolate.Context) (errs []error) { diff --git a/builder/virtualbox/common/step_configure_vrdp.go b/builder/virtualbox/common/step_configure_vrdp.go index 6cc960ad3..54bde727b 100644 --- a/builder/virtualbox/common/step_configure_vrdp.go +++ b/builder/virtualbox/common/step_configure_vrdp.go @@ -4,9 +4,8 @@ import ( "context" "fmt" "log" - "math/rand" - "net" + "github.com/hashicorp/packer/common/net" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -23,33 +22,33 @@ import ( // vrdp_port unit - The port that VRDP is configured to listen on. type StepConfigureVRDP struct { VRDPBindAddress string - VRDPPortMin uint - VRDPPortMax uint + VRDPPortMin int + VRDPPortMax int + + l *net.Listener } -func (s *StepConfigureVRDP) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { +func (s *StepConfigureVRDP) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) log.Printf("Looking for available port between %d and %d on %s", s.VRDPPortMin, s.VRDPPortMax, s.VRDPBindAddress) - var vrdpPort uint - portRange := int(s.VRDPPortMax - s.VRDPPortMin) - - for { - if portRange > 0 { - vrdpPort = uint(rand.Intn(portRange)) + s.VRDPPortMin - } else { - vrdpPort = s.VRDPPortMin - } - - log.Printf("Trying port: %d", vrdpPort) - l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.VRDPBindAddress, vrdpPort)) - if err == nil { - defer l.Close() - break - } + var err error + s.l, err = net.ListenRangeConfig{ + Addr: s.VRDPBindAddress, + Min: s.VRDPPortMin, + Max: s.VRDPPortMax, + Network: "tcp", + }.Listen(ctx) + if err != nil { + err := fmt.Errorf("Error finding port: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } + s.l.Listener.Close() // free port, but don't unlock lock file + vrdpPort := s.l.Port command := []string{ "modifyvm", vmName, @@ -72,4 +71,11 @@ func (s *StepConfigureVRDP) Run(_ context.Context, state multistep.StateBag) mul return multistep.ActionContinue } -func (s *StepConfigureVRDP) Cleanup(state multistep.StateBag) {} +func (s *StepConfigureVRDP) Cleanup(state multistep.StateBag) { + if s.l != nil { + err := s.l.Close() + if err != nil { + log.Printf("failed to unlock port lockfile: %v", err) + } + } +} From 446105e384ca63d078c5cd26bc41cb41abca81bb Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 13:29:12 +0100 Subject: [PATCH 06/20] quemu stepConfigureVNC: use common/net pkg to find open port --- builder/qemu/builder.go | 4 +-- builder/qemu/step_configure_vnc.go | 46 ++++++++++++++++++------------ 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index c30f22f3e..b03adfc28 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -120,8 +120,8 @@ type Config struct { SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` UseDefaultDisplay bool `mapstructure:"use_default_display"` VNCBindAddress string `mapstructure:"vnc_bind_address"` - VNCPortMin uint `mapstructure:"vnc_port_min"` - VNCPortMax uint `mapstructure:"vnc_port_max"` + VNCPortMin int `mapstructure:"vnc_port_min"` + VNCPortMax int `mapstructure:"vnc_port_max"` VMName string `mapstructure:"vm_name"` // These are deprecated, but we keep them around for BC diff --git a/builder/qemu/step_configure_vnc.go b/builder/qemu/step_configure_vnc.go index 1f1cd088d..9e0f2b97a 100644 --- a/builder/qemu/step_configure_vnc.go +++ b/builder/qemu/step_configure_vnc.go @@ -4,9 +4,8 @@ import ( "context" "fmt" "log" - "math/rand" - "net" + "github.com/hashicorp/packer/common/net" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -19,9 +18,11 @@ import ( // // Produces: // vnc_port uint - The port that VNC is configured to listen on. -type stepConfigureVNC struct{} +type stepConfigureVNC struct { + l *net.Listener +} -func (stepConfigureVNC) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { +func (s *stepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) @@ -31,22 +32,22 @@ func (stepConfigureVNC) Run(_ context.Context, state multistep.StateBag) multist msg := fmt.Sprintf("Looking for available port between %d and %d on %s", config.VNCPortMin, config.VNCPortMax, config.VNCBindAddress) ui.Say(msg) log.Print(msg) - var vncPort uint - portRange := int(config.VNCPortMax - config.VNCPortMin) - for { - if portRange > 0 { - vncPort = uint(rand.Intn(portRange)) + config.VNCPortMin - } else { - vncPort = config.VNCPortMin - } - log.Printf("Trying port: %d", vncPort) - l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", config.VNCBindAddress, vncPort)) - if err == nil { - defer l.Close() - break - } + var err error + s.l, err = net.ListenRangeConfig{ + Addr: config.VNCBindAddress, + Min: config.VNCPortMin, + Max: config.VNCPortMax, + Network: "tcp", + }.Listen(ctx) + if err != nil { + err := fmt.Errorf("Error finding port: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } + s.l.Listener.Close() // free port, but don't unlock lock file + vncPort := s.l.Port log.Printf("Found available VNC port: %d on IP: %s", vncPort, config.VNCBindAddress) state.Put("vnc_port", vncPort) @@ -55,4 +56,11 @@ func (stepConfigureVNC) Run(_ context.Context, state multistep.StateBag) multist return multistep.ActionContinue } -func (stepConfigureVNC) Cleanup(multistep.StateBag) {} +func (s *stepConfigureVNC) Cleanup(multistep.StateBag) { + if s.l != nil { + err := s.l.Close() + if err != nil { + log.Printf("failed to unlock port lockfile: %v", err) + } + } +} From ae182a7c20154c19b38f651f7276118074be7795 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 13:31:51 +0100 Subject: [PATCH 07/20] qemu stepForwardSSH: use common/net pkg to find open port --- builder/qemu/step_forward_ssh.go | 49 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/builder/qemu/step_forward_ssh.go b/builder/qemu/step_forward_ssh.go index 6e9efaca1..b525998de 100644 --- a/builder/qemu/step_forward_ssh.go +++ b/builder/qemu/step_forward_ssh.go @@ -4,9 +4,8 @@ import ( "context" "fmt" "log" - "math/rand" - "net" + "github.com/hashicorp/packer/common/net" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -17,31 +16,30 @@ import ( // Uses: // // Produces: -type stepForwardSSH struct{} +type stepForwardSSH struct { + l *net.Listener +} -func (s *stepForwardSSH) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { +func (s *stepForwardSSH) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", config.SSHHostPortMin, config.SSHHostPortMax) - var sshHostPort uint - - portRange := config.SSHHostPortMax - config.SSHHostPortMin + 1 - offset := uint(rand.Intn(int(portRange))) - - for { - sshHostPort = offset + config.SSHHostPortMin - log.Printf("Trying port: %d", sshHostPort) - l, err := net.Listen("tcp", fmt.Sprintf(":%d", sshHostPort)) - if err == nil { - defer l.Close() - break - } - offset++ - if offset == portRange { - offset = 0 - } + var err error + s.l, err = net.ListenRangeConfig{ + Addr: config.VNCBindAddress, + Min: config.VNCPortMin, + Max: config.VNCPortMax, + Network: "tcp", + }.Listen(ctx) + if err != nil { + err := fmt.Errorf("Error finding port: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } + s.l.Listener.Close() // free port, but don't unlock lock file + sshHostPort := s.l.Port ui.Say(fmt.Sprintf("Found port for communicator (SSH, WinRM, etc): %d.", sshHostPort)) // Save the port we're using so that future steps can use it @@ -50,4 +48,11 @@ func (s *stepForwardSSH) Run(_ context.Context, state multistep.StateBag) multis return multistep.ActionContinue } -func (s *stepForwardSSH) Cleanup(state multistep.StateBag) {} +func (s *stepForwardSSH) Cleanup(state multistep.StateBag) { + if s.l != nil { + err := s.l.Close() + if err != nil { + log.Printf("failed to unlock port lockfile: %v", err) + } + } +} From 51294287fa4f0aaa15149d68e8b886ccef1c2bd3 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 16:09:53 +0100 Subject: [PATCH 08/20] StepHTTPServer: display error if we could not connect --- common/step_http_server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/step_http_server.go b/common/step_http_server.go index e8cd1c6ca..b4eb7b00e 100644 --- a/common/step_http_server.go +++ b/common/step_http_server.go @@ -48,6 +48,9 @@ func (s *StepHTTPServer) Run(ctx context.Context, state multistep.StateBag) mult }.Listen(ctx) if err != nil { + err := fmt.Errorf("Error finding port: %s", err) + state.Put("error", err) + ui.Error(err.Error()) return multistep.ActionHalt } From 4cb58446f7988b9b78bad14826f173408356446a Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 16:15:02 +0100 Subject: [PATCH 09/20] packer.CachePath: try to create dir if it doesn't exist --- packer/cache.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packer/cache.go b/packer/cache.go index f878ab565..eac2835fc 100644 --- a/packer/cache.go +++ b/packer/cache.go @@ -11,6 +11,7 @@ var DefaultCacheDir = "packer_cache" // // When the directory is not absolute, CachePath will try to get // current working directory to be able to return a full path. +// CachePath tries to create the resulting path if it doesn't exist. // // CachePath can error in case it cannot find the cwd. // @@ -19,7 +20,11 @@ var DefaultCacheDir = "packer_cache" // PACKER_CACHE_DIR="" CacheDir("foo") => "./packer_cache/foo // PACKER_CACHE_DIR="bar" CacheDir("foo") => "./bar/foo // PACKER_CACHE_DIR="/home/there" CacheDir("foo", "bar") => "/home/there/foo/bar -func CachePath(paths ...string) (string, error) { +func CachePath(paths ...string) (path string, err error) { + defer func() { + // create the dir based on return path it it doesn't exist + os.MkdirAll(path, os.ModePerm) + }() cacheDir := DefaultCacheDir if cd := os.Getenv("PACKER_CACHE_DIR"); cd != "" { cacheDir = cd From c214f6735b3c96cf59dfa55912e787b336917854 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 17:19:03 +0100 Subject: [PATCH 10/20] make everything a uint --- builder/cloudstack/config.go | 2 +- builder/cloudstack/ssh.go | 4 ++-- .../cloudstack/step_configure_networking.go | 18 +++++++++--------- .../cloudstack/step_create_security_group.go | 4 ++-- builder/qemu/builder.go | 4 ++-- builder/qemu/ssh.go | 4 ++-- builder/vagrant/ssh.go | 4 ++-- builder/vagrant/step_ssh_config.go | 2 +- builder/virtualbox/common/run_config.go | 4 ++-- builder/virtualbox/common/ssh.go | 4 ++-- builder/virtualbox/common/ssh_config.go | 4 ++-- .../virtualbox/common/step_configure_vrdp.go | 4 ++-- builder/virtualbox/common/step_forward_ssh.go | 6 +++--- builder/vmware/common/run_config.go | 4 ++-- builder/vmware/common/step_configure_vnc.go | 12 +++++++----- common/http_config.go | 4 ++-- common/net/configure_port.go | 9 ++++----- common/step_http_server.go | 4 ++-- communicator/winrm/communicator.go | 2 +- communicator/winrm/config.go | 2 +- helper/communicator/config.go | 6 +++--- helper/communicator/step_connect.go | 4 ++-- helper/communicator/step_connect_ssh.go | 2 +- helper/communicator/step_connect_winrm.go | 2 +- 24 files changed, 58 insertions(+), 57 deletions(-) diff --git a/builder/cloudstack/config.go b/builder/cloudstack/config.go index f74a89502..5be4c58b1 100644 --- a/builder/cloudstack/config.go +++ b/builder/cloudstack/config.go @@ -37,7 +37,7 @@ type Config struct { Network string `mapstructure:"network"` Project string `mapstructure:"project"` PublicIPAddress string `mapstructure:"public_ip_address"` - PublicPort int `mapstructure:"public_port"` + PublicPort uint `mapstructure:"public_port"` SecurityGroups []string `mapstructure:"security_groups"` ServiceOffering string `mapstructure:"service_offering"` PreventFirewallChanges bool `mapstructure:"prevent_firewall_changes"` diff --git a/builder/cloudstack/ssh.go b/builder/cloudstack/ssh.go index ec9fbe123..f50c7e77d 100644 --- a/builder/cloudstack/ssh.go +++ b/builder/cloudstack/ssh.go @@ -15,8 +15,8 @@ func commHost(state multistep.StateBag) (string, error) { return ip, nil } -func commPort(state multistep.StateBag) (int, error) { - commPort, hasPort := state.Get("commPort").(int) +func commPort(state multistep.StateBag) (uint, error) { + commPort, hasPort := state.Get("commPort").(uint) if !hasPort { return 0, fmt.Errorf("Failed to retrieve communication port") } diff --git a/builder/cloudstack/step_configure_networking.go b/builder/cloudstack/step_configure_networking.go index 39636b54f..a08280f9c 100644 --- a/builder/cloudstack/step_configure_networking.go +++ b/builder/cloudstack/step_configure_networking.go @@ -13,8 +13,8 @@ import ( ) type stepSetupNetworking struct { - privatePort int - publicPort int + privatePort uint + publicPort uint } func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { @@ -36,7 +36,7 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m } else { // Generate a random public port used to configure our port forward. rand.Seed(time.Now().UnixNano()) - s.publicPort = 50000 + rand.Intn(10000) + s.publicPort = uint(50000 + rand.Intn(10000)) } state.Put("commPort", s.publicPort) @@ -99,9 +99,9 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m ui.Message("Creating port forward...") p := client.Firewall.NewCreatePortForwardingRuleParams( config.PublicIPAddress, - s.privatePort, + int(s.privatePort), "TCP", - s.publicPort, + int(s.publicPort), instanceID, ) @@ -143,8 +143,8 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m p.SetAclid(network.Aclid) p.SetAction("allow") p.SetCidrlist(config.CIDRList) - p.SetStartport(s.privatePort) - p.SetEndport(s.privatePort) + p.SetStartport(int(s.privatePort)) + p.SetEndport(int(s.privatePort)) p.SetTraffictype("ingress") // Create the network ACL rule. @@ -166,8 +166,8 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m // Configure the firewall rule. p.SetCidrlist(config.CIDRList) - p.SetStartport(s.publicPort) - p.SetEndport(s.publicPort) + p.SetStartport(int(s.publicPort)) + p.SetEndport(int(s.publicPort)) fwRule, err := client.Firewall.CreateFirewallRule(p) if err != nil { diff --git a/builder/cloudstack/step_create_security_group.go b/builder/cloudstack/step_create_security_group.go index c42eec5d5..1e3e251bc 100644 --- a/builder/cloudstack/step_create_security_group.go +++ b/builder/cloudstack/step_create_security_group.go @@ -54,8 +54,8 @@ func (s *stepCreateSecurityGroup) Run(_ context.Context, state multistep.StateBa i.SetCidrlist(config.CIDRList) i.SetProtocol("TCP") i.SetSecuritygroupid(sg.Id) - i.SetStartport(config.Comm.Port()) - i.SetEndport(config.Comm.Port()) + i.SetStartport(int(config.Comm.Port())) + i.SetEndport(int(config.Comm.Port())) if config.Project != "" { i.SetProjectid(config.Project) } diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index b03adfc28..c30f22f3e 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -120,8 +120,8 @@ type Config struct { SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` UseDefaultDisplay bool `mapstructure:"use_default_display"` VNCBindAddress string `mapstructure:"vnc_bind_address"` - VNCPortMin int `mapstructure:"vnc_port_min"` - VNCPortMax int `mapstructure:"vnc_port_max"` + VNCPortMin uint `mapstructure:"vnc_port_min"` + VNCPortMax uint `mapstructure:"vnc_port_max"` VMName string `mapstructure:"vm_name"` // These are deprecated, but we keep them around for BC diff --git a/builder/qemu/ssh.go b/builder/qemu/ssh.go index ec030df2e..b2f6ed150 100644 --- a/builder/qemu/ssh.go +++ b/builder/qemu/ssh.go @@ -8,7 +8,7 @@ func commHost(state multistep.StateBag) (string, error) { return "127.0.0.1", nil } -func commPort(state multistep.StateBag) (int, error) { +func commPort(state multistep.StateBag) (uint, error) { sshHostPort := state.Get("sshHostPort").(uint) - return int(sshHostPort), nil + return sshHostPort, nil } diff --git a/builder/vagrant/ssh.go b/builder/vagrant/ssh.go index d4a56cb17..4b4f23650 100644 --- a/builder/vagrant/ssh.go +++ b/builder/vagrant/ssh.go @@ -11,8 +11,8 @@ func CommHost() func(multistep.StateBag) (string, error) { } } -func SSHPort() func(multistep.StateBag) (int, error) { - return func(state multistep.StateBag) (int, error) { +func SSHPort() func(multistep.StateBag) (uint, error) { + return func(state multistep.StateBag) (uint, error) { config := state.Get("config").(*Config) return config.Comm.SSHPort, nil } diff --git a/builder/vagrant/step_ssh_config.go b/builder/vagrant/step_ssh_config.go index 68fc13aa3..2a5a878e2 100644 --- a/builder/vagrant/step_ssh_config.go +++ b/builder/vagrant/step_ssh_config.go @@ -44,7 +44,7 @@ func (s *StepSSHConfig) Run(_ context.Context, state multistep.StateBag) multist state.Put("error", err) return multistep.ActionHalt } - config.Comm.SSHPort = port + config.Comm.SSHPort = uint(port) return multistep.ActionContinue } diff --git a/builder/virtualbox/common/run_config.go b/builder/virtualbox/common/run_config.go index e5cae02a6..cf94c306b 100644 --- a/builder/virtualbox/common/run_config.go +++ b/builder/virtualbox/common/run_config.go @@ -10,8 +10,8 @@ type RunConfig struct { Headless bool `mapstructure:"headless"` VRDPBindAddress string `mapstructure:"vrdp_bind_address"` - VRDPPortMin int `mapstructure:"vrdp_port_min"` - VRDPPortMax int `mapstructure:"vrdp_port_max"` + VRDPPortMin uint `mapstructure:"vrdp_port_min"` + VRDPPortMax uint `mapstructure:"vrdp_port_max"` } func (c *RunConfig) Prepare(ctx *interpolate.Context) (errs []error) { diff --git a/builder/virtualbox/common/ssh.go b/builder/virtualbox/common/ssh.go index 7734dc6b2..494274e15 100644 --- a/builder/virtualbox/common/ssh.go +++ b/builder/virtualbox/common/ssh.go @@ -10,7 +10,7 @@ func CommHost(host string) func(multistep.StateBag) (string, error) { } } -func SSHPort(state multistep.StateBag) (int, error) { - sshHostPort := state.Get("sshHostPort").(int) +func SSHPort(state multistep.StateBag) (uint, error) { + sshHostPort := state.Get("sshHostPort").(uint) return sshHostPort, nil } diff --git a/builder/virtualbox/common/ssh_config.go b/builder/virtualbox/common/ssh_config.go index 10159cc86..3136bca98 100644 --- a/builder/virtualbox/common/ssh_config.go +++ b/builder/virtualbox/common/ssh_config.go @@ -11,8 +11,8 @@ import ( type SSHConfig struct { Comm communicator.Config `mapstructure:",squash"` - SSHHostPortMin int `mapstructure:"ssh_host_port_min"` - SSHHostPortMax int `mapstructure:"ssh_host_port_max"` + SSHHostPortMin uint `mapstructure:"ssh_host_port_min"` + SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` SSHSkipNatMapping bool `mapstructure:"ssh_skip_nat_mapping"` // These are deprecated, but we keep them around for BC diff --git a/builder/virtualbox/common/step_configure_vrdp.go b/builder/virtualbox/common/step_configure_vrdp.go index 54bde727b..ea14723d3 100644 --- a/builder/virtualbox/common/step_configure_vrdp.go +++ b/builder/virtualbox/common/step_configure_vrdp.go @@ -22,8 +22,8 @@ import ( // vrdp_port unit - The port that VRDP is configured to listen on. type StepConfigureVRDP struct { VRDPBindAddress string - VRDPPortMin int - VRDPPortMax int + VRDPPortMin uint + VRDPPortMax uint l *net.Listener } diff --git a/builder/virtualbox/common/step_forward_ssh.go b/builder/virtualbox/common/step_forward_ssh.go index 345b9c55f..5f5c6fd62 100644 --- a/builder/virtualbox/common/step_forward_ssh.go +++ b/builder/virtualbox/common/step_forward_ssh.go @@ -22,8 +22,8 @@ import ( // Produces: type StepForwardSSH struct { CommConfig *communicator.Config - HostPortMin int - HostPortMax int + HostPortMin uint + HostPortMax uint SkipNatMapping bool l *net.Listener @@ -40,7 +40,7 @@ func (s *StepForwardSSH) Run(ctx context.Context, state multistep.StateBag) mult return multistep.ActionContinue } - guestPort := s.CommConfig.Port() + guestPort := uint(s.CommConfig.Port()) sshHostPort := guestPort if !s.SkipNatMapping { log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", diff --git a/builder/vmware/common/run_config.go b/builder/vmware/common/run_config.go index e8b6a3d37..c4bfc3413 100644 --- a/builder/vmware/common/run_config.go +++ b/builder/vmware/common/run_config.go @@ -10,8 +10,8 @@ type RunConfig struct { Headless bool `mapstructure:"headless"` VNCBindAddress string `mapstructure:"vnc_bind_address"` - VNCPortMin int `mapstructure:"vnc_port_min"` - VNCPortMax int `mapstructure:"vnc_port_max"` + VNCPortMin uint `mapstructure:"vnc_port_min"` + VNCPortMax uint `mapstructure:"vnc_port_max"` VNCDisablePassword bool `mapstructure:"vnc_disable_password"` } diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index 284c58edd..b3ef92bf3 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -18,12 +18,12 @@ import ( // vmx_path string // // Produces: -// vnc_port int - The port that VNC is configured to listen on. +// vnc_port uint - The port that VNC is configured to listen on. type StepConfigureVNC struct { Enabled bool VNCBindAddress string - VNCPortMin int - VNCPortMax int + VNCPortMin uint + VNCPortMax uint VNCDisablePassword bool l *net.Listener @@ -31,7 +31,7 @@ type StepConfigureVNC struct { type VNCAddressFinder interface { // UpdateVMX, sets driver specific VNC values to VMX data. - UpdateVMX(vncAddress, vncPassword string, vncPort int, vmxData map[string]string) + UpdateVMX(vncAddress, vncPassword string, vncPort uint, vmxData map[string]string) } func VNCPassword(skipPassword bool) string { @@ -105,12 +105,14 @@ func (s *StepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) mu return multistep.ActionHalt } + state.Put("vnc_port", s.l.Port) + state.Put("vnc_ip", s.l.Address) state.Put("vnc_password", vncPassword) return multistep.ActionContinue } -func (*StepConfigureVNC) UpdateVMX(address, password string, port int, data map[string]string) { +func (StepConfigureVNC) UpdateVMX(address, password string, port uint, data map[string]string) { data["remotedisplay.vnc.enabled"] = "TRUE" data["remotedisplay.vnc.port"] = fmt.Sprintf("%d", port) data["remotedisplay.vnc.ip"] = address diff --git a/common/http_config.go b/common/http_config.go index 8a6809ac4..bb9b46b26 100644 --- a/common/http_config.go +++ b/common/http_config.go @@ -9,8 +9,8 @@ import ( // HTTPConfig contains configuration for the local HTTP Server type HTTPConfig struct { HTTPDir string `mapstructure:"http_directory"` - HTTPPortMin int `mapstructure:"http_port_min"` - HTTPPortMax int `mapstructure:"http_port_max"` + HTTPPortMin uint `mapstructure:"http_port_min"` + HTTPPortMax uint `mapstructure:"http_port_max"` } func (c *HTTPConfig) Prepare(ctx *interpolate.Context) []error { diff --git a/common/net/configure_port.go b/common/net/configure_port.go index cb1fe66bf..91fbf5f17 100644 --- a/common/net/configure_port.go +++ b/common/net/configure_port.go @@ -7,7 +7,6 @@ import ( "log" "math/rand" "net" - "strconv" "github.com/gofrs/flock" @@ -25,7 +24,7 @@ type Listener struct { // Listener can be closed but Port will be file locked by packer until // Close is called. net.Listener - Port int + Port uint Address string lock *flock.Flock } @@ -44,7 +43,7 @@ type ListenRangeConfig struct { // tcp", "udp" Network string Addr string - Min, Max int + Min, Max uint net.ListenConfig } @@ -65,9 +64,9 @@ func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { return nil, err } - port := rand.Intn(portRange) + lc.Min + port := uint(rand.Intn(portRange)) + lc.Min - lockFilePath, err := packer.CachePath("port", strconv.Itoa(port)) + lockFilePath, err := packer.CachePath("port", fmt.Sprintf("%d", port)) if err != nil { return nil, err } diff --git a/common/step_http_server.go b/common/step_http_server.go index b4eb7b00e..282d4f969 100644 --- a/common/step_http_server.go +++ b/common/step_http_server.go @@ -23,8 +23,8 @@ import ( // http_port int - The port the HTTP server started on. type StepHTTPServer struct { HTTPDir string - HTTPPortMin int - HTTPPortMax int + HTTPPortMin uint + HTTPPortMax uint l *net.Listener } diff --git a/communicator/winrm/communicator.go b/communicator/winrm/communicator.go index fc639ccb0..09f125508 100644 --- a/communicator/winrm/communicator.go +++ b/communicator/winrm/communicator.go @@ -27,7 +27,7 @@ type Communicator struct { func New(config *Config) (*Communicator, error) { endpoint := &winrm.Endpoint{ Host: config.Host, - Port: config.Port, + Port: int(config.Port), // it's a uint HTTPS: config.Https, Insecure: config.Insecure, diff --git a/communicator/winrm/config.go b/communicator/winrm/config.go index 728336734..44ec989c0 100644 --- a/communicator/winrm/config.go +++ b/communicator/winrm/config.go @@ -9,7 +9,7 @@ import ( // Config is used to configure the WinRM connection type Config struct { Host string - Port int + Port uint Username string Password string Timeout time.Duration diff --git a/helper/communicator/config.go b/helper/communicator/config.go index fa02810d7..80d148e63 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -25,7 +25,7 @@ type Config struct { // SSH SSHHost string `mapstructure:"ssh_host"` - SSHPort int `mapstructure:"ssh_port"` + SSHPort uint `mapstructure:"ssh_port"` SSHUsername string `mapstructure:"ssh_username"` SSHPassword string `mapstructure:"ssh_password"` SSHKeyPairName string `mapstructure:"ssh_keypair_name"` @@ -60,7 +60,7 @@ type Config struct { WinRMUser string `mapstructure:"winrm_username"` WinRMPassword string `mapstructure:"winrm_password"` WinRMHost string `mapstructure:"winrm_host"` - WinRMPort int `mapstructure:"winrm_port"` + WinRMPort uint `mapstructure:"winrm_port"` WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` WinRMUseSSL bool `mapstructure:"winrm_use_ssl"` WinRMInsecure bool `mapstructure:"winrm_insecure"` @@ -150,7 +150,7 @@ func (c *Config) SSHConfigFunc() func(multistep.StateBag) (*ssh.ClientConfig, er } // Port returns the port that will be used for access based on config. -func (c *Config) Port() int { +func (c *Config) Port() uint { switch c.Type { case "ssh": return c.SSHPort diff --git a/helper/communicator/step_connect.go b/helper/communicator/step_connect.go index 6bb062f80..eed1fe7b4 100644 --- a/helper/communicator/step_connect.go +++ b/helper/communicator/step_connect.go @@ -28,14 +28,14 @@ type StepConnect struct { // SSHConfig should return the default configuration for // connecting via SSH. SSHConfig func(multistep.StateBag) (*gossh.ClientConfig, error) - SSHPort func(multistep.StateBag) (int, error) + SSHPort func(multistep.StateBag) (uint, error) // The fields below are callbacks to assist with connecting to WinRM. // // WinRMConfig should return the default configuration for // connecting via WinRM. WinRMConfig func(multistep.StateBag) (*WinRMConfig, error) - WinRMPort func(multistep.StateBag) (int, error) + WinRMPort func(multistep.StateBag) (uint, error) // CustomConnect can be set to have custom connectors for specific // types. These take highest precedence so you can also override diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index 37db32eae..6d6c10271 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -27,7 +27,7 @@ type StepConnectSSH struct { Config *Config Host func(multistep.StateBag) (string, error) SSHConfig func(multistep.StateBag) (*gossh.ClientConfig, error) - SSHPort func(multistep.StateBag) (int, error) + SSHPort func(multistep.StateBag) (uint, error) } func (s *StepConnectSSH) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { diff --git a/helper/communicator/step_connect_winrm.go b/helper/communicator/step_connect_winrm.go index 06e6236f8..6c7e5d456 100644 --- a/helper/communicator/step_connect_winrm.go +++ b/helper/communicator/step_connect_winrm.go @@ -30,7 +30,7 @@ type StepConnectWinRM struct { Config *Config Host func(multistep.StateBag) (string, error) WinRMConfig func(multistep.StateBag) (*WinRMConfig, error) - WinRMPort func(multistep.StateBag) (int, error) + WinRMPort func(multistep.StateBag) (uint, error) } func (s *StepConnectWinRM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { From 025fc87278cd920bf6bde879ab5ba8e119306ec9 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Mon, 18 Mar 2019 17:49:49 +0100 Subject: [PATCH 11/20] StepConnectSSH: show connection address in debug output --- helper/communicator/step_connect_ssh.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index 6d6c10271..032768dd0 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -186,7 +186,8 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru Timeout: s.Config.SSHReadWriteTimeout, } - log.Println("[INFO] Attempting SSH connection...") + log.Println("[INFO] Attempting SSH connection to %s...", address) + log.Println("[DEBUG] Config to %#v...", config) comm, err = ssh.New(address, config) if err != nil { log.Printf("[DEBUG] SSH handshake err: %s", err) From f828b72c10233fb69d304e30e3bbd888612d170a Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 19 Mar 2019 10:42:08 +0100 Subject: [PATCH 12/20] step configure vnc: allow to use ESX5Driver again --- builder/vmware/common/driver_esx5.go | 3 +- builder/vmware/common/step_configure_vnc.go | 33 +++++++++++++++------ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/builder/vmware/common/driver_esx5.go b/builder/vmware/common/driver_esx5.go index b82aac7b2..903203496 100644 --- a/builder/vmware/common/driver_esx5.go +++ b/builder/vmware/common/driver_esx5.go @@ -3,6 +3,7 @@ package common import ( "bufio" "bytes" + "context" "encoding/csv" "errors" "fmt" @@ -359,7 +360,7 @@ func (d *ESX5Driver) GuestAddress(multistep.StateBag) (string, error) { return result, nil } -func (d *ESX5Driver) VNCAddress(_ string, portMin, portMax uint) (string, uint, error) { +func (d *ESX5Driver) VNCAddress(ctx context.Context, _ string, portMin, portMax uint) (string, uint, error) { var vncPort uint //Process ports ESXi is listening on to determine which are available diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index b3ef92bf3..7e5e0c3a2 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -30,10 +30,28 @@ type StepConfigureVNC struct { } type VNCAddressFinder interface { + VNCAddress(context.Context, string, uint, uint) (string, uint, error) + // UpdateVMX, sets driver specific VNC values to VMX data. UpdateVMX(vncAddress, vncPassword string, vncPort uint, vmxData map[string]string) } +func (s *StepConfigureVNC) VNCAddress(ctx context.Context, vncBindAddress string, portMin, portMax uint) (string, uint, error) { + var err error + s.l, err = net.ListenRangeConfig{ + Addr: s.VNCBindAddress, + Min: s.VNCPortMin, + Max: s.VNCPortMax, + Network: "tcp", + }.Listen(ctx) + if err != nil { + return "", 0, err + } + + s.l.Listener.Close() + return s.l.Address, s.l.Port, nil +} + func VNCPassword(skipPassword bool) string { if skipPassword { return "" @@ -78,12 +96,7 @@ func (s *StepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) mu } log.Printf("Looking for available port between %d and %d", s.VNCPortMin, s.VNCPortMax) - s.l, err = net.ListenRangeConfig{ - Addr: s.VNCBindAddress, - Min: s.VNCPortMin, - Max: s.VNCPortMax, - Network: "tcp", - }.Listen(ctx) + vncBindAddress, vncPort, err := vncFinder.VNCAddress(ctx, s.VNCBindAddress, s.VNCPortMin, s.VNCPortMax) if err != nil { state.Put("error", err) @@ -96,7 +109,7 @@ func (s *StepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) mu log.Printf("Found available VNC port: %v", s.l) - vncFinder.UpdateVMX(s.l.Address, vncPassword, s.l.Port, vmxData) + vncFinder.UpdateVMX(vncBindAddress, vncPassword, vncPort, vmxData) if err := WriteVMX(vmxPath, vmxData); err != nil { err := fmt.Errorf("Error writing VMX data: %s", err) @@ -122,7 +135,9 @@ func (StepConfigureVNC) UpdateVMX(address, password string, port uint, data map[ } func (s *StepConfigureVNC) Cleanup(multistep.StateBag) { - if err := s.l.Close(); err != nil { - log.Printf("failed to unlock port lockfile: %v", err) + if s.l != nil { + if err := s.l.Close(); err != nil { + log.Printf("failed to unlock port lockfile: %v", err) + } } } From 5a6dffde9a4380125d1dacc36c4a6dca63dbe22a Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 19 Mar 2019 14:47:21 +0100 Subject: [PATCH 13/20] use port as ints --- builder/cloudstack/config.go | 2 +- builder/cloudstack/ssh.go | 4 ++-- .../cloudstack/step_configure_networking.go | 18 +++++++++--------- builder/cloudstack/step_create_instance.go | 4 ++-- .../cloudstack/step_create_security_group.go | 4 ++-- .../hyperv/common/step_type_boot_command.go | 4 ++-- builder/hyperv/iso/builder_test.go | 2 +- builder/hyperv/vmcx/builder_test.go | 2 +- .../parallels/common/step_type_boot_command.go | 4 ++-- builder/parallels/pvm/builder.go | 2 +- builder/qemu/builder.go | 8 ++++---- builder/qemu/ssh.go | 6 +++--- builder/qemu/step_configure_vnc.go | 2 +- builder/qemu/step_run.go | 14 +++++++------- builder/qemu/step_type_boot_command.go | 8 ++++---- builder/vagrant/ssh.go | 4 ++-- builder/vagrant/step_ssh_config.go | 2 +- builder/virtualbox/common/run_config.go | 4 ++-- builder/virtualbox/common/ssh.go | 4 ++-- builder/virtualbox/common/ssh_config.go | 4 ++-- .../virtualbox/common/step_configure_vrdp.go | 4 ++-- builder/virtualbox/common/step_forward_ssh.go | 6 +++--- builder/virtualbox/common/step_run.go | 2 +- .../common/step_type_boot_command.go | 4 ++-- builder/vmware/common/driver_config.go | 2 +- builder/vmware/common/driver_esx5.go | 8 ++++---- builder/vmware/common/driver_esx5_test.go | 2 +- builder/vmware/common/run_config.go | 4 ++-- builder/vmware/common/step_configure_vnc.go | 14 +++++++------- builder/vmware/common/step_run.go | 2 +- .../vmware/common/step_type_boot_command.go | 8 ++++---- common/http_config.go | 4 ++-- common/http_config_test.go | 4 ++-- common/net/configure_port.go | 9 +++++---- common/step_http_server.go | 6 +++--- communicator/winrm/communicator.go | 2 +- communicator/winrm/config.go | 2 +- config.go | 4 ++-- helper/communicator/config.go | 6 +++--- helper/communicator/step_connect.go | 4 ++-- helper/communicator/step_connect_ssh.go | 2 +- helper/communicator/step_connect_winrm.go | 2 +- packer/plugin/client.go | 2 +- provisioner/ansible/provisioner.go | 5 ++--- provisioner/ansible/provisioner_test.go | 4 ++-- provisioner/inspec/provisioner.go | 7 +++---- provisioner/inspec/provisioner_test.go | 4 ++-- 47 files changed, 112 insertions(+), 113 deletions(-) diff --git a/builder/cloudstack/config.go b/builder/cloudstack/config.go index 5be4c58b1..f74a89502 100644 --- a/builder/cloudstack/config.go +++ b/builder/cloudstack/config.go @@ -37,7 +37,7 @@ type Config struct { Network string `mapstructure:"network"` Project string `mapstructure:"project"` PublicIPAddress string `mapstructure:"public_ip_address"` - PublicPort uint `mapstructure:"public_port"` + PublicPort int `mapstructure:"public_port"` SecurityGroups []string `mapstructure:"security_groups"` ServiceOffering string `mapstructure:"service_offering"` PreventFirewallChanges bool `mapstructure:"prevent_firewall_changes"` diff --git a/builder/cloudstack/ssh.go b/builder/cloudstack/ssh.go index f50c7e77d..ec9fbe123 100644 --- a/builder/cloudstack/ssh.go +++ b/builder/cloudstack/ssh.go @@ -15,8 +15,8 @@ func commHost(state multistep.StateBag) (string, error) { return ip, nil } -func commPort(state multistep.StateBag) (uint, error) { - commPort, hasPort := state.Get("commPort").(uint) +func commPort(state multistep.StateBag) (int, error) { + commPort, hasPort := state.Get("commPort").(int) if !hasPort { return 0, fmt.Errorf("Failed to retrieve communication port") } diff --git a/builder/cloudstack/step_configure_networking.go b/builder/cloudstack/step_configure_networking.go index a08280f9c..39636b54f 100644 --- a/builder/cloudstack/step_configure_networking.go +++ b/builder/cloudstack/step_configure_networking.go @@ -13,8 +13,8 @@ import ( ) type stepSetupNetworking struct { - privatePort uint - publicPort uint + privatePort int + publicPort int } func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { @@ -36,7 +36,7 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m } else { // Generate a random public port used to configure our port forward. rand.Seed(time.Now().UnixNano()) - s.publicPort = uint(50000 + rand.Intn(10000)) + s.publicPort = 50000 + rand.Intn(10000) } state.Put("commPort", s.publicPort) @@ -99,9 +99,9 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m ui.Message("Creating port forward...") p := client.Firewall.NewCreatePortForwardingRuleParams( config.PublicIPAddress, - int(s.privatePort), + s.privatePort, "TCP", - int(s.publicPort), + s.publicPort, instanceID, ) @@ -143,8 +143,8 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m p.SetAclid(network.Aclid) p.SetAction("allow") p.SetCidrlist(config.CIDRList) - p.SetStartport(int(s.privatePort)) - p.SetEndport(int(s.privatePort)) + p.SetStartport(s.privatePort) + p.SetEndport(s.privatePort) p.SetTraffictype("ingress") // Create the network ACL rule. @@ -166,8 +166,8 @@ func (s *stepSetupNetworking) Run(_ context.Context, state multistep.StateBag) m // Configure the firewall rule. p.SetCidrlist(config.CIDRList) - p.SetStartport(int(s.publicPort)) - p.SetEndport(int(s.publicPort)) + p.SetStartport(s.publicPort) + p.SetEndport(s.publicPort) fwRule, err := client.Firewall.CreateFirewallRule(p) if err != nil { diff --git a/builder/cloudstack/step_create_instance.go b/builder/cloudstack/step_create_instance.go index 11303f46e..6cc97ae0a 100644 --- a/builder/cloudstack/step_create_instance.go +++ b/builder/cloudstack/step_create_instance.go @@ -18,7 +18,7 @@ import ( // userDataTemplateData represents variables for user_data interpolation type userDataTemplateData struct { HTTPIP string - HTTPPort uint + HTTPPort int } // stepCreateInstance represents a Packer build step that creates CloudStack instances. @@ -86,7 +86,7 @@ func (s *stepCreateInstance) Run(_ context.Context, state multistep.StateBag) mu } if config.UserData != "" { - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) httpIP, err := hostIP() if err != nil { err := fmt.Errorf("Failed to determine host IP: %s", err) diff --git a/builder/cloudstack/step_create_security_group.go b/builder/cloudstack/step_create_security_group.go index 1e3e251bc..c42eec5d5 100644 --- a/builder/cloudstack/step_create_security_group.go +++ b/builder/cloudstack/step_create_security_group.go @@ -54,8 +54,8 @@ func (s *stepCreateSecurityGroup) Run(_ context.Context, state multistep.StateBa i.SetCidrlist(config.CIDRList) i.SetProtocol("TCP") i.SetSecuritygroupid(sg.Id) - i.SetStartport(int(config.Comm.Port())) - i.SetEndport(int(config.Comm.Port())) + i.SetStartport(config.Comm.Port()) + i.SetEndport(config.Comm.Port()) if config.Project != "" { i.SetProjectid(config.Project) } diff --git a/builder/hyperv/common/step_type_boot_command.go b/builder/hyperv/common/step_type_boot_command.go index dc4b27c85..0d296ce8c 100644 --- a/builder/hyperv/common/step_type_boot_command.go +++ b/builder/hyperv/common/step_type_boot_command.go @@ -15,7 +15,7 @@ import ( type bootCommandTemplateData struct { HTTPIP string - HTTPPort uint + HTTPPort int Name string } @@ -29,7 +29,7 @@ type StepTypeBootCommand struct { } func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) ui := state.Get("ui").(packer.Ui) driver := state.Get("driver").(Driver) vmName := state.Get("vmName").(string) diff --git a/builder/hyperv/iso/builder_test.go b/builder/hyperv/iso/builder_test.go index a79ae4d87..a07ab38bd 100644 --- a/builder/hyperv/iso/builder_test.go +++ b/builder/hyperv/iso/builder_test.go @@ -610,7 +610,7 @@ func TestUserVariablesInBootCommand(t *testing.T) { state.Put("config", &b.config) state.Put("driver", driver) state.Put("hook", hook) - state.Put("http_port", uint(0)) + state.Put("http_port", 0) state.Put("ui", ui) state.Put("vmName", "packer-foo") diff --git a/builder/hyperv/vmcx/builder_test.go b/builder/hyperv/vmcx/builder_test.go index 60c36735b..735d1be8a 100644 --- a/builder/hyperv/vmcx/builder_test.go +++ b/builder/hyperv/vmcx/builder_test.go @@ -511,7 +511,7 @@ func TestUserVariablesInBootCommand(t *testing.T) { state.Put("config", &b.config) state.Put("driver", driver) state.Put("hook", hook) - state.Put("http_port", uint(0)) + state.Put("http_port", 0) state.Put("ui", ui) state.Put("vmName", "packer-foo") diff --git a/builder/parallels/common/step_type_boot_command.go b/builder/parallels/common/step_type_boot_command.go index 4e1e47b20..83abd28c2 100644 --- a/builder/parallels/common/step_type_boot_command.go +++ b/builder/parallels/common/step_type_boot_command.go @@ -14,7 +14,7 @@ import ( type bootCommandTemplateData struct { HTTPIP string - HTTPPort uint + HTTPPort int Name string } @@ -32,7 +32,7 @@ type StepTypeBootCommand struct { // Run types the boot command by sending key scancodes into the VM. func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { debug := state.Get("debug").(bool) - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) ui := state.Get("ui").(packer.Ui) driver := state.Get("driver").(Driver) diff --git a/builder/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index 72af59f5c..001801849 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/builder.go @@ -46,7 +46,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { state.Put("driver", driver) state.Put("hook", hook) state.Put("ui", ui) - state.Put("http_port", uint(0)) + state.Put("http_port", 0) // Build the steps. steps := []multistep.Step{ diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index c30f22f3e..7d42939a4 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -116,12 +116,12 @@ type Config struct { QemuArgs [][]string `mapstructure:"qemuargs"` QemuBinary string `mapstructure:"qemu_binary"` ShutdownCommand string `mapstructure:"shutdown_command"` - SSHHostPortMin uint `mapstructure:"ssh_host_port_min"` - SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` + SSHHostPortMin int `mapstructure:"ssh_host_port_min"` + SSHHostPortMax int `mapstructure:"ssh_host_port_max"` UseDefaultDisplay bool `mapstructure:"use_default_display"` VNCBindAddress string `mapstructure:"vnc_bind_address"` - VNCPortMin uint `mapstructure:"vnc_port_min"` - VNCPortMax uint `mapstructure:"vnc_port_max"` + VNCPortMin int `mapstructure:"vnc_port_min"` + VNCPortMax int `mapstructure:"vnc_port_max"` VMName string `mapstructure:"vm_name"` // These are deprecated, but we keep them around for BC diff --git a/builder/qemu/ssh.go b/builder/qemu/ssh.go index b2f6ed150..1fe4537bd 100644 --- a/builder/qemu/ssh.go +++ b/builder/qemu/ssh.go @@ -8,7 +8,7 @@ func commHost(state multistep.StateBag) (string, error) { return "127.0.0.1", nil } -func commPort(state multistep.StateBag) (uint, error) { - sshHostPort := state.Get("sshHostPort").(uint) - return sshHostPort, nil +func commPort(state multistep.StateBag) (int, error) { + sshHostPort := state.Get("sshHostPort").(int) + return int(sshHostPort), nil } diff --git a/builder/qemu/step_configure_vnc.go b/builder/qemu/step_configure_vnc.go index 9e0f2b97a..465288e7f 100644 --- a/builder/qemu/step_configure_vnc.go +++ b/builder/qemu/step_configure_vnc.go @@ -17,7 +17,7 @@ import ( // ui packer.Ui // // Produces: -// vnc_port uint - The port that VNC is configured to listen on. +// vnc_port int - The port that VNC is configured to listen on. type stepConfigureVNC struct { l *net.Listener } diff --git a/builder/qemu/step_run.go b/builder/qemu/step_run.go index c806e10dd..aea087795 100644 --- a/builder/qemu/step_run.go +++ b/builder/qemu/step_run.go @@ -21,11 +21,11 @@ type stepRun struct { type qemuArgsTemplateData struct { HTTPIP string - HTTPPort uint + HTTPPort int HTTPDir string OutputDir string Name string - SSHHostPort uint + SSHHostPort int } func (s *stepRun) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { @@ -63,7 +63,7 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error config := state.Get("config").(*Config) isoPath := state.Get("iso_path").(string) vncIP := state.Get("vnc_ip").(string) - vncPort := state.Get("vnc_port").(uint) + vncPort := state.Get("vnc_port").(int) ui := state.Get("ui").(packer.Ui) driver := state.Get("driver").(Driver) @@ -74,12 +74,12 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error defaultArgs := make(map[string]interface{}) var deviceArgs []string var driveArgs []string - var sshHostPort uint + var sshHostPort int defaultArgs["-name"] = vmName defaultArgs["-machine"] = fmt.Sprintf("type=%s", config.MachineType) if config.Comm.Type != "none" { - sshHostPort = state.Get("sshHostPort").(uint) + sshHostPort = state.Get("sshHostPort").(int) defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0,hostfwd=tcp::%v-:%d", sshHostPort, config.Comm.Port()) } else { defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0") @@ -121,7 +121,7 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error if vncIpOk && vncPortOk { vncIp := vncIpRaw.(string) - vncPort := vncPortRaw.(uint) + vncPort := vncPortRaw.(int) ui.Message(fmt.Sprintf( "The VM will be run headless, without a GUI. If you want to\n"+ @@ -175,7 +175,7 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error if len(config.QemuArgs) > 0 { ui.Say("Overriding defaults Qemu arguments with QemuArgs...") - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) ctx := config.ctx if config.Comm.Type != "none" { ctx.Data = qemuArgsTemplateData{ diff --git a/builder/qemu/step_type_boot_command.go b/builder/qemu/step_type_boot_command.go index 86e838d25..b524967cb 100644 --- a/builder/qemu/step_type_boot_command.go +++ b/builder/qemu/step_type_boot_command.go @@ -19,7 +19,7 @@ const KeyLeftShift uint32 = 0xFFE1 type bootCommandTemplateData struct { HTTPIP string - HTTPPort uint + HTTPPort int Name string } @@ -29,7 +29,7 @@ type bootCommandTemplateData struct { // config *config // http_port int // ui packer.Ui -// vnc_port uint +// vnc_port int // // Produces: // @@ -38,9 +38,9 @@ type stepTypeBootCommand struct{} func (s *stepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) debug := state.Get("debug").(bool) - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) ui := state.Get("ui").(packer.Ui) - vncPort := state.Get("vnc_port").(uint) + vncPort := state.Get("vnc_port").(int) vncIP := state.Get("vnc_ip").(string) if config.VNCConfig.DisableVNC { diff --git a/builder/vagrant/ssh.go b/builder/vagrant/ssh.go index 4b4f23650..d4a56cb17 100644 --- a/builder/vagrant/ssh.go +++ b/builder/vagrant/ssh.go @@ -11,8 +11,8 @@ func CommHost() func(multistep.StateBag) (string, error) { } } -func SSHPort() func(multistep.StateBag) (uint, error) { - return func(state multistep.StateBag) (uint, error) { +func SSHPort() func(multistep.StateBag) (int, error) { + return func(state multistep.StateBag) (int, error) { config := state.Get("config").(*Config) return config.Comm.SSHPort, nil } diff --git a/builder/vagrant/step_ssh_config.go b/builder/vagrant/step_ssh_config.go index 2a5a878e2..68fc13aa3 100644 --- a/builder/vagrant/step_ssh_config.go +++ b/builder/vagrant/step_ssh_config.go @@ -44,7 +44,7 @@ func (s *StepSSHConfig) Run(_ context.Context, state multistep.StateBag) multist state.Put("error", err) return multistep.ActionHalt } - config.Comm.SSHPort = uint(port) + config.Comm.SSHPort = port return multistep.ActionContinue } diff --git a/builder/virtualbox/common/run_config.go b/builder/virtualbox/common/run_config.go index cf94c306b..e5cae02a6 100644 --- a/builder/virtualbox/common/run_config.go +++ b/builder/virtualbox/common/run_config.go @@ -10,8 +10,8 @@ type RunConfig struct { Headless bool `mapstructure:"headless"` VRDPBindAddress string `mapstructure:"vrdp_bind_address"` - VRDPPortMin uint `mapstructure:"vrdp_port_min"` - VRDPPortMax uint `mapstructure:"vrdp_port_max"` + VRDPPortMin int `mapstructure:"vrdp_port_min"` + VRDPPortMax int `mapstructure:"vrdp_port_max"` } func (c *RunConfig) Prepare(ctx *interpolate.Context) (errs []error) { diff --git a/builder/virtualbox/common/ssh.go b/builder/virtualbox/common/ssh.go index 494274e15..7734dc6b2 100644 --- a/builder/virtualbox/common/ssh.go +++ b/builder/virtualbox/common/ssh.go @@ -10,7 +10,7 @@ func CommHost(host string) func(multistep.StateBag) (string, error) { } } -func SSHPort(state multistep.StateBag) (uint, error) { - sshHostPort := state.Get("sshHostPort").(uint) +func SSHPort(state multistep.StateBag) (int, error) { + sshHostPort := state.Get("sshHostPort").(int) return sshHostPort, nil } diff --git a/builder/virtualbox/common/ssh_config.go b/builder/virtualbox/common/ssh_config.go index 3136bca98..10159cc86 100644 --- a/builder/virtualbox/common/ssh_config.go +++ b/builder/virtualbox/common/ssh_config.go @@ -11,8 +11,8 @@ import ( type SSHConfig struct { Comm communicator.Config `mapstructure:",squash"` - SSHHostPortMin uint `mapstructure:"ssh_host_port_min"` - SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` + SSHHostPortMin int `mapstructure:"ssh_host_port_min"` + SSHHostPortMax int `mapstructure:"ssh_host_port_max"` SSHSkipNatMapping bool `mapstructure:"ssh_skip_nat_mapping"` // These are deprecated, but we keep them around for BC diff --git a/builder/virtualbox/common/step_configure_vrdp.go b/builder/virtualbox/common/step_configure_vrdp.go index ea14723d3..54bde727b 100644 --- a/builder/virtualbox/common/step_configure_vrdp.go +++ b/builder/virtualbox/common/step_configure_vrdp.go @@ -22,8 +22,8 @@ import ( // vrdp_port unit - The port that VRDP is configured to listen on. type StepConfigureVRDP struct { VRDPBindAddress string - VRDPPortMin uint - VRDPPortMax uint + VRDPPortMin int + VRDPPortMax int l *net.Listener } diff --git a/builder/virtualbox/common/step_forward_ssh.go b/builder/virtualbox/common/step_forward_ssh.go index 5f5c6fd62..345b9c55f 100644 --- a/builder/virtualbox/common/step_forward_ssh.go +++ b/builder/virtualbox/common/step_forward_ssh.go @@ -22,8 +22,8 @@ import ( // Produces: type StepForwardSSH struct { CommConfig *communicator.Config - HostPortMin uint - HostPortMax uint + HostPortMin int + HostPortMax int SkipNatMapping bool l *net.Listener @@ -40,7 +40,7 @@ func (s *StepForwardSSH) Run(ctx context.Context, state multistep.StateBag) mult return multistep.ActionContinue } - guestPort := uint(s.CommConfig.Port()) + guestPort := s.CommConfig.Port() sshHostPort := guestPort if !s.SkipNatMapping { log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", diff --git a/builder/virtualbox/common/step_run.go b/builder/virtualbox/common/step_run.go index 689b58602..d3a3fb66b 100644 --- a/builder/virtualbox/common/step_run.go +++ b/builder/virtualbox/common/step_run.go @@ -35,7 +35,7 @@ func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.Ste if vrdpIpOk && vrdpPortOk { vrdpIp := vrdpIpRaw.(string) - vrdpPort := vrdpPortRaw.(uint) + vrdpPort := vrdpPortRaw.(int) ui.Message(fmt.Sprintf( "The VM will be run headless, without a GUI. If you want to\n"+ diff --git a/builder/virtualbox/common/step_type_boot_command.go b/builder/virtualbox/common/step_type_boot_command.go index fb596cc82..88d92f321 100644 --- a/builder/virtualbox/common/step_type_boot_command.go +++ b/builder/virtualbox/common/step_type_boot_command.go @@ -22,7 +22,7 @@ type bootCommandTemplateData struct { HTTPIP string // HTTPPort is the HTTP server port. - HTTPPort uint + HTTPPort int // Name is the VM's name. Name string @@ -43,7 +43,7 @@ type StepTypeBootCommand struct { func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { debug := state.Get("debug").(bool) driver := state.Get("driver").(Driver) - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/vmware/common/driver_config.go b/builder/vmware/common/driver_config.go index b600ae237..1add0bb10 100644 --- a/builder/vmware/common/driver_config.go +++ b/builder/vmware/common/driver_config.go @@ -20,7 +20,7 @@ type DriverConfig struct { RemoteCacheDatastore string `mapstructure:"remote_cache_datastore"` RemoteCacheDirectory string `mapstructure:"remote_cache_directory"` RemoteHost string `mapstructure:"remote_host"` - RemotePort uint `mapstructure:"remote_port"` + RemotePort int `mapstructure:"remote_port"` RemoteUser string `mapstructure:"remote_username"` RemotePassword string `mapstructure:"remote_password"` RemotePrivateKey string `mapstructure:"remote_private_key_file"` diff --git a/builder/vmware/common/driver_esx5.go b/builder/vmware/common/driver_esx5.go index 903203496..5d8ef49cd 100644 --- a/builder/vmware/common/driver_esx5.go +++ b/builder/vmware/common/driver_esx5.go @@ -31,7 +31,7 @@ type ESX5Driver struct { base VmwareDriver Host string - Port uint + Port int Username string Password string PrivateKeyFile string @@ -360,8 +360,8 @@ func (d *ESX5Driver) GuestAddress(multistep.StateBag) (string, error) { return result, nil } -func (d *ESX5Driver) VNCAddress(ctx context.Context, _ string, portMin, portMax uint) (string, uint, error) { - var vncPort uint +func (d *ESX5Driver) VNCAddress(ctx context.Context, _ string, portMin, portMax int) (string, int, error) { + var vncPort int //Process ports ESXi is listening on to determine which are available //This process does best effort to detect ports that are unavailable, @@ -427,7 +427,7 @@ func (d *ESX5Driver) VNCAddress(ctx context.Context, _ string, portMin, portMax } // UpdateVMX, adds the VNC port to the VMX data. -func (ESX5Driver) UpdateVMX(_, password string, port uint, data map[string]string) { +func (ESX5Driver) UpdateVMX(_, password string, port int, data map[string]string) { // Do not set remotedisplay.vnc.ip - this breaks ESXi. data["remotedisplay.vnc.enabled"] = "TRUE" data["remotedisplay.vnc.port"] = fmt.Sprintf("%d", port) diff --git a/builder/vmware/common/driver_esx5_test.go b/builder/vmware/common/driver_esx5_test.go index 38232bbe7..67b18ee8a 100644 --- a/builder/vmware/common/driver_esx5_test.go +++ b/builder/vmware/common/driver_esx5_test.go @@ -50,7 +50,7 @@ func TestESX5Driver_HostIP(t *testing.T) { port := listen.Addr().(*net.TCPAddr).Port defer listen.Close() - driver := ESX5Driver{Host: "localhost", Port: uint(port)} + driver := ESX5Driver{Host: "localhost", Port: port} state := new(multistep.BasicStateBag) if host, _ := driver.HostIP(state); host != expected_host { diff --git a/builder/vmware/common/run_config.go b/builder/vmware/common/run_config.go index c4bfc3413..e8b6a3d37 100644 --- a/builder/vmware/common/run_config.go +++ b/builder/vmware/common/run_config.go @@ -10,8 +10,8 @@ type RunConfig struct { Headless bool `mapstructure:"headless"` VNCBindAddress string `mapstructure:"vnc_bind_address"` - VNCPortMin uint `mapstructure:"vnc_port_min"` - VNCPortMax uint `mapstructure:"vnc_port_max"` + VNCPortMin int `mapstructure:"vnc_port_min"` + VNCPortMax int `mapstructure:"vnc_port_max"` VNCDisablePassword bool `mapstructure:"vnc_disable_password"` } diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index 7e5e0c3a2..9fbf3ba1f 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -18,25 +18,25 @@ import ( // vmx_path string // // Produces: -// vnc_port uint - The port that VNC is configured to listen on. +// vnc_port int - The port that VNC is configured to listen on. type StepConfigureVNC struct { Enabled bool VNCBindAddress string - VNCPortMin uint - VNCPortMax uint + VNCPortMin int + VNCPortMax int VNCDisablePassword bool l *net.Listener } type VNCAddressFinder interface { - VNCAddress(context.Context, string, uint, uint) (string, uint, error) + VNCAddress(context.Context, string, int, int) (string, int, error) // UpdateVMX, sets driver specific VNC values to VMX data. - UpdateVMX(vncAddress, vncPassword string, vncPort uint, vmxData map[string]string) + UpdateVMX(vncAddress, vncPassword string, vncPort int, vmxData map[string]string) } -func (s *StepConfigureVNC) VNCAddress(ctx context.Context, vncBindAddress string, portMin, portMax uint) (string, uint, error) { +func (s *StepConfigureVNC) VNCAddress(ctx context.Context, vncBindAddress string, portMin, portMax int) (string, int, error) { var err error s.l, err = net.ListenRangeConfig{ Addr: s.VNCBindAddress, @@ -125,7 +125,7 @@ func (s *StepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) mu return multistep.ActionContinue } -func (StepConfigureVNC) UpdateVMX(address, password string, port uint, data map[string]string) { +func (*StepConfigureVNC) UpdateVMX(address, password string, port int, data map[string]string) { data["remotedisplay.vnc.enabled"] = "TRUE" data["remotedisplay.vnc.port"] = fmt.Sprintf("%d", port) data["remotedisplay.vnc.ip"] = address diff --git a/builder/vmware/common/step_run.go b/builder/vmware/common/step_run.go index 2dad6faed..953d8ea5a 100644 --- a/builder/vmware/common/step_run.go +++ b/builder/vmware/common/step_run.go @@ -43,7 +43,7 @@ func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.Ste if vncIpOk && vncPortOk && vncPasswordOk { vncIp := vncIpRaw.(string) - vncPort := vncPortRaw.(uint) + vncPort := vncPortRaw.(int) vncPassword := vncPasswordRaw.(string) ui.Message(fmt.Sprintf( diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index b241d57ba..ad615f6a4 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -20,7 +20,7 @@ import ( // Uses: // http_port int // ui packer.Ui -// vnc_port uint +// vnc_port int // // Produces: // @@ -34,7 +34,7 @@ type StepTypeBootCommand struct { } type bootCommandTemplateData struct { HTTPIP string - HTTPPort uint + HTTPPort int Name string } @@ -46,10 +46,10 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) debug := state.Get("debug").(bool) driver := state.Get("driver").(Driver) - httpPort := state.Get("http_port").(uint) + httpPort := state.Get("http_port").(int) ui := state.Get("ui").(packer.Ui) vncIp := state.Get("vnc_ip").(string) - vncPort := state.Get("vnc_port").(uint) + vncPort := state.Get("vnc_port").(int) vncPassword := state.Get("vnc_password") // Wait the for the vm to boot. diff --git a/common/http_config.go b/common/http_config.go index bb9b46b26..8a6809ac4 100644 --- a/common/http_config.go +++ b/common/http_config.go @@ -9,8 +9,8 @@ import ( // HTTPConfig contains configuration for the local HTTP Server type HTTPConfig struct { HTTPDir string `mapstructure:"http_directory"` - HTTPPortMin uint `mapstructure:"http_port_min"` - HTTPPortMax uint `mapstructure:"http_port_max"` + HTTPPortMin int `mapstructure:"http_port_min"` + HTTPPortMax int `mapstructure:"http_port_max"` } func (c *HTTPConfig) Prepare(ctx *interpolate.Context) []error { diff --git a/common/http_config_test.go b/common/http_config_test.go index eb42148b8..02b800845 100644 --- a/common/http_config_test.go +++ b/common/http_config_test.go @@ -24,11 +24,11 @@ func TestHTTPConfigPrepare_Bounds(t *testing.T) { if err != nil { t.Fatalf("should not have error: %s", err) } - portMin := uint(8000) + portMin := 8000 if h.HTTPPortMin != portMin { t.Fatalf("HTTPPortMin: expected %d got %d", portMin, h.HTTPPortMin) } - portMax := uint(9000) + portMax := 9000 if h.HTTPPortMax != portMax { t.Fatalf("HTTPPortMax: expected %d got %d", portMax, h.HTTPPortMax) } diff --git a/common/net/configure_port.go b/common/net/configure_port.go index 91fbf5f17..cb1fe66bf 100644 --- a/common/net/configure_port.go +++ b/common/net/configure_port.go @@ -7,6 +7,7 @@ import ( "log" "math/rand" "net" + "strconv" "github.com/gofrs/flock" @@ -24,7 +25,7 @@ type Listener struct { // Listener can be closed but Port will be file locked by packer until // Close is called. net.Listener - Port uint + Port int Address string lock *flock.Flock } @@ -43,7 +44,7 @@ type ListenRangeConfig struct { // tcp", "udp" Network string Addr string - Min, Max uint + Min, Max int net.ListenConfig } @@ -64,9 +65,9 @@ func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { return nil, err } - port := uint(rand.Intn(portRange)) + lc.Min + port := rand.Intn(portRange) + lc.Min - lockFilePath, err := packer.CachePath("port", fmt.Sprintf("%d", port)) + lockFilePath, err := packer.CachePath("port", strconv.Itoa(port)) if err != nil { return nil, err } diff --git a/common/step_http_server.go b/common/step_http_server.go index 282d4f969..b78abc657 100644 --- a/common/step_http_server.go +++ b/common/step_http_server.go @@ -23,8 +23,8 @@ import ( // http_port int - The port the HTTP server started on. type StepHTTPServer struct { HTTPDir string - HTTPPortMin uint - HTTPPortMax uint + HTTPPortMin int + HTTPPortMax int l *net.Listener } @@ -33,7 +33,7 @@ func (s *StepHTTPServer) Run(ctx context.Context, state multistep.StateBag) mult ui := state.Get("ui").(packer.Ui) if s.HTTPDir == "" { - state.Put("http_port", uint(0)) + state.Put("http_port", 0) return multistep.ActionContinue } diff --git a/communicator/winrm/communicator.go b/communicator/winrm/communicator.go index 09f125508..fc639ccb0 100644 --- a/communicator/winrm/communicator.go +++ b/communicator/winrm/communicator.go @@ -27,7 +27,7 @@ type Communicator struct { func New(config *Config) (*Communicator, error) { endpoint := &winrm.Endpoint{ Host: config.Host, - Port: int(config.Port), // it's a uint + Port: config.Port, HTTPS: config.Https, Insecure: config.Insecure, diff --git a/communicator/winrm/config.go b/communicator/winrm/config.go index 44ec989c0..728336734 100644 --- a/communicator/winrm/config.go +++ b/communicator/winrm/config.go @@ -9,7 +9,7 @@ import ( // Config is used to configure the WinRM connection type Config struct { Host string - Port uint + Port int Username string Password string Timeout time.Duration diff --git a/config.go b/config.go index 409b8f12d..1b7946b24 100644 --- a/config.go +++ b/config.go @@ -24,8 +24,8 @@ const PACKERSPACE = "-PACKERSPACE-" type config struct { DisableCheckpoint bool `json:"disable_checkpoint"` DisableCheckpointSignature bool `json:"disable_checkpoint_signature"` - PluginMinPort uint - PluginMaxPort uint + PluginMinPort int + PluginMaxPort int Builders map[string]string PostProcessors map[string]string `json:"post-processors"` diff --git a/helper/communicator/config.go b/helper/communicator/config.go index 80d148e63..fa02810d7 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -25,7 +25,7 @@ type Config struct { // SSH SSHHost string `mapstructure:"ssh_host"` - SSHPort uint `mapstructure:"ssh_port"` + SSHPort int `mapstructure:"ssh_port"` SSHUsername string `mapstructure:"ssh_username"` SSHPassword string `mapstructure:"ssh_password"` SSHKeyPairName string `mapstructure:"ssh_keypair_name"` @@ -60,7 +60,7 @@ type Config struct { WinRMUser string `mapstructure:"winrm_username"` WinRMPassword string `mapstructure:"winrm_password"` WinRMHost string `mapstructure:"winrm_host"` - WinRMPort uint `mapstructure:"winrm_port"` + WinRMPort int `mapstructure:"winrm_port"` WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` WinRMUseSSL bool `mapstructure:"winrm_use_ssl"` WinRMInsecure bool `mapstructure:"winrm_insecure"` @@ -150,7 +150,7 @@ func (c *Config) SSHConfigFunc() func(multistep.StateBag) (*ssh.ClientConfig, er } // Port returns the port that will be used for access based on config. -func (c *Config) Port() uint { +func (c *Config) Port() int { switch c.Type { case "ssh": return c.SSHPort diff --git a/helper/communicator/step_connect.go b/helper/communicator/step_connect.go index eed1fe7b4..6bb062f80 100644 --- a/helper/communicator/step_connect.go +++ b/helper/communicator/step_connect.go @@ -28,14 +28,14 @@ type StepConnect struct { // SSHConfig should return the default configuration for // connecting via SSH. SSHConfig func(multistep.StateBag) (*gossh.ClientConfig, error) - SSHPort func(multistep.StateBag) (uint, error) + SSHPort func(multistep.StateBag) (int, error) // The fields below are callbacks to assist with connecting to WinRM. // // WinRMConfig should return the default configuration for // connecting via WinRM. WinRMConfig func(multistep.StateBag) (*WinRMConfig, error) - WinRMPort func(multistep.StateBag) (uint, error) + WinRMPort func(multistep.StateBag) (int, error) // CustomConnect can be set to have custom connectors for specific // types. These take highest precedence so you can also override diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index 032768dd0..b17fd5424 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -27,7 +27,7 @@ type StepConnectSSH struct { Config *Config Host func(multistep.StateBag) (string, error) SSHConfig func(multistep.StateBag) (*gossh.ClientConfig, error) - SSHPort func(multistep.StateBag) (uint, error) + SSHPort func(multistep.StateBag) (int, error) } func (s *StepConnectSSH) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { diff --git a/helper/communicator/step_connect_winrm.go b/helper/communicator/step_connect_winrm.go index 6c7e5d456..06e6236f8 100644 --- a/helper/communicator/step_connect_winrm.go +++ b/helper/communicator/step_connect_winrm.go @@ -30,7 +30,7 @@ type StepConnectWinRM struct { Config *Config Host func(multistep.StateBag) (string, error) WinRMConfig func(multistep.StateBag) (*WinRMConfig, error) - WinRMPort func(multistep.StateBag) (uint, error) + WinRMPort func(multistep.StateBag) (int, error) } func (s *StepConnectWinRM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { diff --git a/packer/plugin/client.go b/packer/plugin/client.go index edcab1d7a..7cfcb8e21 100644 --- a/packer/plugin/client.go +++ b/packer/plugin/client.go @@ -56,7 +56,7 @@ type ClientConfig struct { // The minimum and maximum port to use for communicating with // the subprocess. If not set, this defaults to 10,000 and 25,000 // respectively. - MinPort, MaxPort uint + MinPort, MaxPort int // StartTimeout is the timeout to wait for the plugin to say it // has started successfully. diff --git a/provisioner/ansible/provisioner.go b/provisioner/ansible/provisioner.go index e836eb894..9b28c2bbb 100644 --- a/provisioner/ansible/provisioner.go +++ b/provisioner/ansible/provisioner.go @@ -52,7 +52,7 @@ type Config struct { EmptyGroups []string `mapstructure:"empty_groups"` HostAlias string `mapstructure:"host_alias"` User string `mapstructure:"user"` - LocalPort uint `mapstructure:"local_port"` + LocalPort int `mapstructure:"local_port"` SSHHostKeyFile string `mapstructure:"ssh_host_key_file"` SSHAuthorizedKeyFile string `mapstructure:"ssh_authorized_key_file"` SFTPCmd string `mapstructure:"sftp_command"` @@ -271,12 +271,11 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ui.Say(err.Error()) continue } - portUint64, err := strconv.ParseUint(portStr, 10, 0) + p.config.LocalPort, err = strconv.Atoi(portStr) if err != nil { ui.Say(err.Error()) continue } - p.config.LocalPort = uint(portUint64) return l, nil } return nil, errors.New("Error setting up SSH proxy connection") diff --git a/provisioner/ansible/provisioner_test.go b/provisioner/ansible/provisioner_test.go index 099f72bcc..7905f5600 100644 --- a/provisioner/ansible/provisioner_test.go +++ b/provisioner/ansible/provisioner_test.go @@ -245,13 +245,13 @@ func TestProvisionerPrepare_LocalPort(t *testing.T) { config["ssh_authorized_key_file"] = publickey_file.Name() config["playbook_file"] = playbook_file.Name() - config["local_port"] = uint(65537) + config["local_port"] = 65537 err = p.Prepare(config) if err == nil { t.Fatal("should have error") } - config["local_port"] = uint(22222) + config["local_port"] = 22222 err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) diff --git a/provisioner/inspec/provisioner.go b/provisioner/inspec/provisioner.go index fab92ee49..ae8048f05 100644 --- a/provisioner/inspec/provisioner.go +++ b/provisioner/inspec/provisioner.go @@ -52,7 +52,7 @@ type Config struct { Backend string `mapstructure:"backend"` User string `mapstructure:"user"` Host string `mapstructure:"host"` - LocalPort uint `mapstructure:"local_port"` + LocalPort int `mapstructure:"local_port"` SSHHostKeyFile string `mapstructure:"ssh_host_key_file"` SSHAuthorizedKeyFile string `mapstructure:"ssh_authorized_key_file"` } @@ -264,12 +264,11 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ui.Say(err.Error()) continue } - portUint64, err := strconv.ParseUint(portStr, 10, 0) + p.config.LocalPort, err = strconv.Atoi(portStr) if err != nil { ui.Say(err.Error()) continue } - p.config.LocalPort = uint(portUint64) return l, nil } return nil, errors.New("Error setting up SSH proxy connection") @@ -338,7 +337,7 @@ func (p *Provisioner) executeInspec(ui packer.Ui, comm packer.Communicator, priv args = append(args, "--key-files", privKeyFile) } args = append(args, "--user", p.config.User) - args = append(args, "--port", strconv.FormatUint(uint64(p.config.LocalPort), 10)) + args = append(args, "--port", strconv.Itoa(p.config.LocalPort)) } args = append(args, "--attrs") diff --git a/provisioner/inspec/provisioner_test.go b/provisioner/inspec/provisioner_test.go index 6857f7004..f814768a9 100644 --- a/provisioner/inspec/provisioner_test.go +++ b/provisioner/inspec/provisioner_test.go @@ -254,13 +254,13 @@ func TestProvisionerPrepare_LocalPort(t *testing.T) { config["ssh_authorized_key_file"] = publickey_file.Name() config["profile"] = profile_file.Name() - config["local_port"] = uint(65537) + config["local_port"] = 65537 err = p.Prepare(config) if err == nil { t.Fatal("should have error") } - config["local_port"] = uint(22222) + config["local_port"] = 22222 err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) From a3838ecfadf1ca2fb826a535355f56082d6cdc22 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 19 Mar 2019 15:21:09 +0100 Subject: [PATCH 14/20] error on negative ports --- builder/qemu/builder.go | 4 ++++ builder/vmware/common/run_config.go | 3 +++ 2 files changed, 7 insertions(+) diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index 7d42939a4..5ca3f555b 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -337,6 +337,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend( errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max")) } + if b.config.SSHHostPortMin < 0 { + errs = packer.MultiErrorAppend( + errs, errors.New("ssh_host_port_min must be positive")) + } if b.config.VNCPortMin > b.config.VNCPortMax { errs = packer.MultiErrorAppend( diff --git a/builder/vmware/common/run_config.go b/builder/vmware/common/run_config.go index e8b6a3d37..da9581427 100644 --- a/builder/vmware/common/run_config.go +++ b/builder/vmware/common/run_config.go @@ -31,6 +31,9 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) (errs []error) { if c.VNCPortMin > c.VNCPortMax { errs = append(errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max")) } + if c.VNCPortMin < 0 { + errs = append(errs, fmt.Errorf("vnc_port_min must be positive")) + } return } From 42107c2b8b5ec84cebe7c464078f1ad788b6ecf0 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 19 Mar 2019 15:30:01 +0100 Subject: [PATCH 15/20] CachePath: only create base path --- packer/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packer/cache.go b/packer/cache.go index eac2835fc..958a2367b 100644 --- a/packer/cache.go +++ b/packer/cache.go @@ -23,7 +23,7 @@ var DefaultCacheDir = "packer_cache" func CachePath(paths ...string) (path string, err error) { defer func() { // create the dir based on return path it it doesn't exist - os.MkdirAll(path, os.ModePerm) + os.MkdirAll(filepath.Base(path), os.ModePerm) }() cacheDir := DefaultCacheDir if cd := os.Getenv("PACKER_CACHE_DIR"); cd != "" { From 7737458d17fa4ea32e3f5f1be0ed62901382ce7b Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 19 Mar 2019 15:32:43 +0100 Subject: [PATCH 16/20] fix log output --- helper/communicator/step_connect_ssh.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index b17fd5424..2eb975b99 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -186,8 +186,8 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru Timeout: s.Config.SSHReadWriteTimeout, } - log.Println("[INFO] Attempting SSH connection to %s...", address) - log.Println("[DEBUG] Config to %#v...", config) + log.Printf("[INFO] Attempting SSH connection to %s...", address) + log.Printf("[DEBUG] Config to %#v...", config) comm, err = ssh.New(address, config) if err != nil { log.Printf("[DEBUG] SSH handshake err: %s", err) From cd39aa9988f423268baa0adfdbbea448ca556be2 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 26 Mar 2019 10:45:32 +0100 Subject: [PATCH 17/20] net.ListenRangeConfig.Listen: log tried ports a bit earlier in the process so we know tried ports every time --- common/net/configure_port.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/net/configure_port.go b/common/net/configure_port.go index cb1fe66bf..5117b60cf 100644 --- a/common/net/configure_port.go +++ b/common/net/configure_port.go @@ -67,6 +67,8 @@ func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { port := rand.Intn(portRange) + lc.Min + log.Printf("Trying port: %d", port) + lockFilePath, err := packer.CachePath("port", strconv.Itoa(port)) if err != nil { return nil, err @@ -81,8 +83,6 @@ func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { continue // this port seems to be locked by another packer goroutine } - log.Printf("Trying port: %d", port) - l, err := lc.ListenConfig.Listen(ctx, lc.Network, fmt.Sprintf("%s:%d", lc.Addr, port)) if err != nil { if err := lock.Unlock(); err != nil { From a4a83be2b928976a4ffae1d233f31ab99ad903ac Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 26 Mar 2019 10:52:07 +0100 Subject: [PATCH 18/20] net.ListenRangeConfig.Listen: allow to have a port rage of zero --- common/net/configure_port.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/common/net/configure_port.go b/common/net/configure_port.go index 5117b60cf..b3feca38e 100644 --- a/common/net/configure_port.go +++ b/common/net/configure_port.go @@ -2,7 +2,6 @@ package net import ( "context" - "errors" "fmt" "log" "math/rand" @@ -55,17 +54,16 @@ func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { if lc.Max < lc.Min { lc.Min, lc.Max = lc.Max, lc.Min } - portRange := int(lc.Max - lc.Min) - if portRange == 0 { - // Intn will panic if portRange == 0 - return nil, errors.New("ListenRandomPort: port range is zero") - } + portRange := lc.Max - lc.Min for { if err := ctx.Err(); err != nil { return nil, err } - port := rand.Intn(portRange) + lc.Min + port := lc.Min + if portRange > 0 { + port += rand.Intn(portRange) + } log.Printf("Trying port: %d", port) From 91cc7e1091b9c309039e4ff372350b61a934dd8b Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 26 Mar 2019 10:53:52 +0100 Subject: [PATCH 19/20] net.ListenRangeConfig.Listen: don't swap ports if max < min --- common/net/configure_port.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/common/net/configure_port.go b/common/net/configure_port.go index b3feca38e..dbce7ee8f 100644 --- a/common/net/configure_port.go +++ b/common/net/configure_port.go @@ -51,9 +51,6 @@ type ListenRangeConfig struct { // until ctx is cancelled. // Listen uses net.ListenConfig.Listen internally. func (lc ListenRangeConfig) Listen(ctx context.Context) (*Listener, error) { - if lc.Max < lc.Min { - lc.Min, lc.Max = lc.Max, lc.Min - } portRange := lc.Max - lc.Min for { if err := ctx.Err(); err != nil { From ac92916b01fd4107f6105fb0a76f60f559c4b4a0 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 26 Mar 2019 10:58:51 +0100 Subject: [PATCH 20/20] StepConfigureVNC: close listener only once --- builder/vmware/common/step_configure_vnc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index 9fbf3ba1f..1b426ea63 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -48,7 +48,7 @@ func (s *StepConfigureVNC) VNCAddress(ctx context.Context, vncBindAddress string return "", 0, err } - s.l.Listener.Close() + s.l.Listener.Close() // free port, but don't unlock lock file return s.l.Address, s.l.Port, nil } @@ -103,7 +103,6 @@ func (s *StepConfigureVNC) Run(ctx context.Context, state multistep.StateBag) mu ui.Error(err.Error()) return multistep.ActionHalt } - s.l.Listener.Close() // free port, but don't unlock lock file vncPassword := VNCPassword(s.VNCDisablePassword)