From af009c2aa0957526004ce2ba38c19cebc965ce8d Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Tue, 7 Jul 2020 15:37:45 -0700 Subject: [PATCH] make tunnel timeout configurable --- builder/googlecompute/config.go | 3 +++ builder/googlecompute/step_start_tunnel.go | 12 ++++++++---- builder/googlecompute/step_start_tunnel_test.go | 8 +++++--- builder/googlecompute/tunnel_driver.go | 4 ++-- builder/googlecompute/tunnel_driver_windows.go | 4 ++-- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index c7fd17aeb..2b306f6e2 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -425,6 +425,9 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) { c.IAPConfig.IAPExt = ".cmd" } } + if c.IAPConfig.IAPTunnelLaunchTimeout == 0 { + c.IAPConfig.IAPTunnelLaunchTimeout = 30 + } // Configure IAP: Update SSH config to use localhost proxy instead if c.IAPConfig.IAP { diff --git a/builder/googlecompute/step_start_tunnel.go b/builder/googlecompute/step_start_tunnel.go index 434d7fe4e..e1ad60bff 100644 --- a/builder/googlecompute/step_start_tunnel.go +++ b/builder/googlecompute/step_start_tunnel.go @@ -51,14 +51,17 @@ type IAPConfig struct { // What file extension to use for script that sets up gcloud. // Default: ".sh" IAPExt string `mapstructure:"iap_ext" required:"false"` + // How long to wait, in seconds, before assuming a tunnel launch was + // successful. Defaults to 30 seconds. + IAPTunnelLaunchTimeout int `mapstructure:"iap_tunnel_launch_timeout" required:"false"` } type TunnelDriver interface { - StartTunnel(context.Context, string) error + StartTunnel(context.Context, string, int) error StopTunnel() } -func RunTunnelCommand(cmd *exec.Cmd) error { +func RunTunnelCommand(cmd *exec.Cmd, timeout int) error { // set stdout and stderr so we can read what's going on. var stdout, stderr bytes.Buffer cmd.Stdout = &stdout @@ -78,7 +81,8 @@ func RunTunnelCommand(cmd *exec.Cmd) error { // afternoon trying to figure out how to get the SDK to actually send // the "Listening on port [n]" line I see when I run it manually, and I // can't justify spending more time than that on aesthetics. - for i := 0; i < 30; i++ { + + for i := 0; i < timeout; i++ { time.Sleep(1 * time.Second) lineStderr, err := stderr.ReadString('\n') @@ -307,7 +311,7 @@ func (s *StepStartTunnel) Run(ctx context.Context, state multistep.StateBag) mul RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { // tunnel launcher/destroyer has to be different on windows vs. unix. - err := s.tunnelDriver.StartTunnel(ctx, tempScriptFileName) + err := s.tunnelDriver.StartTunnel(ctx, tempScriptFileName, s.IAPConf.IAPTunnelLaunchTimeout) return err }) if err != nil { diff --git a/builder/googlecompute/step_start_tunnel_test.go b/builder/googlecompute/step_start_tunnel_test.go index 47813df8e..b82411e86 100644 --- a/builder/googlecompute/step_start_tunnel_test.go +++ b/builder/googlecompute/step_start_tunnel_test.go @@ -12,16 +12,18 @@ import ( ) type MockTunnelDriver struct { - StopTunnelCalled bool - StartTunnelCalled bool + StopTunnelCalled bool + StartTunnelCalled bool + StartTunnelTimeout int } func (m *MockTunnelDriver) StopTunnel() { m.StopTunnelCalled = true } -func (m *MockTunnelDriver) StartTunnel(context.Context, string) error { +func (m *MockTunnelDriver) StartTunnel(_ context.Context, _ string, timeout int) error { m.StartTunnelCalled = true + m.StartTunnelTimeout = timeout return nil } diff --git a/builder/googlecompute/tunnel_driver.go b/builder/googlecompute/tunnel_driver.go index 8bd5e0a56..d9ab2f9de 100644 --- a/builder/googlecompute/tunnel_driver.go +++ b/builder/googlecompute/tunnel_driver.go @@ -17,11 +17,11 @@ type TunnelDriverLinux struct { cmd *exec.Cmd } -func (t *TunnelDriverLinux) StartTunnel(cancelCtx context.Context, tempScriptFileName string) error { +func (t *TunnelDriverLinux) StartTunnel(cancelCtx context.Context, tempScriptFileName string, timeout int) error { cmd := exec.CommandContext(cancelCtx, tempScriptFileName) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - err := RunTunnelCommand(cmd) + err := RunTunnelCommand(cmd, timeout) if err != nil { return err } diff --git a/builder/googlecompute/tunnel_driver_windows.go b/builder/googlecompute/tunnel_driver_windows.go index 110b945a3..d40a66293 100644 --- a/builder/googlecompute/tunnel_driver_windows.go +++ b/builder/googlecompute/tunnel_driver_windows.go @@ -16,10 +16,10 @@ type TunnelDriverWindows struct { cmd *exec.Cmd } -func (t *TunnelDriverWindows) StartTunnel(cancelCtx context.Context, tempScriptFileName string) error { +func (t *TunnelDriverWindows) StartTunnel(cancelCtx context.Context, tempScriptFileName string, timeout int) error { args := []string{"/C", "call", tempScriptFileName} cmd := exec.CommandContext(cancelCtx, "cmd", args...) - err := RunTunnelCommand(cmd) + err := RunTunnelCommand(cmd, timeout) if err != nil { return err }