func (p *Provisioner) windowsInstallChefClient( o terraform.UIOutput, comm communicator.Communicator) error { script := path.Join(path.Dir(comm.ScriptPath()), "ChefClient.ps1") content := fmt.Sprintf(installScript, p.Version, p.HTTPProxy, strings.Join(p.NOProxy, ",")) // Copy the script to the new instance if err := comm.UploadScript(script, strings.NewReader(content)); err != nil { return fmt.Errorf("Uploading client.rb failed: %v", err) } // Execute the script to install Chef Client installCmd := fmt.Sprintf("powershell -NoProfile -ExecutionPolicy Bypass -File %s", script) return p.runCommand(o, comm, installCmd) }
// runScripts is used to copy and execute a set of scripts func (p *ResourceProvisioner) runScripts( o terraform.UIOutput, comm communicator.Communicator, scripts []io.ReadCloser) error { // Wait and retry until we establish the connection err := retryFunc(comm.Timeout(), func() error { err := comm.Connect(o) return err }) if err != nil { return err } defer comm.Disconnect() for _, script := range scripts { var cmd *remote.Cmd outR, outW := io.Pipe() errR, errW := io.Pipe() outDoneCh := make(chan struct{}) errDoneCh := make(chan struct{}) go p.copyOutput(o, outR, outDoneCh) go p.copyOutput(o, errR, errDoneCh) err = retryFunc(comm.Timeout(), func() error { remotePath := comm.ScriptPath() if err := comm.UploadScript(remotePath, script); err != nil { return fmt.Errorf("Failed to upload script: %v", err) } cmd = &remote.Cmd{ Command: remotePath, Stdout: outW, Stderr: errW, } if err := comm.Start(cmd); err != nil { return fmt.Errorf("Error starting script: %v", err) } // Upload a blank follow up file in the same path to prevent residual // script contents from remaining on remote machine empty := bytes.NewReader([]byte("")) if err := comm.Upload(remotePath, empty); err != nil { return fmt.Errorf("Failed to upload empty follow up script: %v", err) } return nil }) if err == nil { cmd.Wait() if cmd.ExitStatus != 0 { err = fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus) } } // Wait for output to clean up outW.Close() errW.Close() <-outDoneCh <-errDoneCh // If we have an error, return it out now that we've cleaned up if err != nil { return err } } return nil }