diff --git a/builder/googlecompute/step_start_tunnel.go b/builder/googlecompute/step_start_tunnel.go index 7536f705c..202cf1819 100644 --- a/builder/googlecompute/step_start_tunnel.go +++ b/builder/googlecompute/step_start_tunnel.go @@ -100,7 +100,7 @@ func (s *StepStartTunnel) createTempGcloudScript(args []string) (string, error) s.IAPConf.IAPHashBang = fmt.Sprintf("#!%s\n", s.IAPConf.IAPHashBang) log.Printf("[INFO] (google): Prepending inline gcloud setup script with %s", s.IAPConf.IAPHashBang) - err = writer.WriteString(s.IAPConf.IAPHashBang) + _, err = writer.WriteString(s.IAPConf.IAPHashBang) if err != nil { return "", fmt.Errorf("Error preparing inline hashbang: %s", err) } diff --git a/builder/googlecompute/tunnel_driver.go b/builder/googlecompute/tunnel_driver.go index 78d9be634..1a6ef0bd5 100644 --- a/builder/googlecompute/tunnel_driver.go +++ b/builder/googlecompute/tunnel_driver.go @@ -64,7 +64,7 @@ func (t *TunnelDriverLinux) StartTunnel(cancelCtx context.Context, tempScriptFil func (t *TunnelDriverLinux) StopTunnel() { if t.cmd != nil && t.cmd.Process != nil { log.Printf("Cleaning up the IAP tunnel...") - // Why not just s.cmd.Process.Kill()? I'm glad you asked. The gcloud + // Why not just cmd.Process.Kill()? I'm glad you asked. The gcloud // call spawns a python subprocess that listens on the port, and you // need to use the process _group_ id to kill this process and its // daemon child. We create the group ID with the syscall.SysProcAttr diff --git a/builder/googlecompute/tunnel_driver_windows.go b/builder/googlecompute/tunnel_driver_windows.go index 9d5031ebc..73d739b5a 100644 --- a/builder/googlecompute/tunnel_driver_windows.go +++ b/builder/googlecompute/tunnel_driver_windows.go @@ -3,8 +3,13 @@ package googlecompute import ( + "bytes" "context" "fmt" + "log" + "os/exec" + "strings" + "time" ) func NewTunnelDriver() TunnelDriver { @@ -12,10 +17,54 @@ func NewTunnelDriver() TunnelDriver { } type TunnelDriverWindows struct { + cmd *exec.Cmd } func (t *TunnelDriverWindows) StartTunnel(cancelCtx context.Context, tempScriptFileName string) error { - return fmt.Errorf("Windows support for IAP tunnel not yet supported.") + // set stdout and stderr so we can read what's going on. + var stdout, stderr bytes.Buffer + + cmd := exec.CommandContext(cancelCtx, tempScriptFileName) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err := cmd.Start() + log.Printf("Waiting 30s for tunnel to create...") + if err != nil { + err := fmt.Errorf("Error calling gcloud sdk to launch IAP tunnel: %s", + err) + return err + } + // Wait for tunnel to launch and gather response. TODO: do this without + // a sleep. + time.Sleep(30 * time.Second) + + // Track stdout. + sout := stdout.String() + if sout != "" { + log.Printf("[start-iap-tunnel] stdout is:") + } + + log.Printf("[start-iap-tunnel] stderr is:") + serr := stderr.String() + log.Println(serr) + if strings.Contains(serr, "ERROR") { + errIdx := strings.Index(serr, "ERROR:") + return fmt.Errorf("ERROR: %s", serr[errIdx+7:]) + } + // Store successful command on step so we can access it to cancel it + // later. + t.cmd = cmd + return nil } -func (t *TunnelDriverWindows) StopTunnel() {} +func (t *TunnelDriverWindows) StopTunnel() { + if t.cmd != nil && t.cmd.Process != nil { + err := t.cmd.Process.Kill() + if err != nil { + log.Printf("Issue stopping IAP tunnel: %s", err) + } + } else { + log.Printf("Couldn't find IAP tunnel process to kill. Continuing.") + } +}