diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 8696f3fa2..5e59848b3 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -119,6 +119,10 @@ type Config struct { // Run pwsh.exe instead of powershell.exe - latest version of powershell. UsePwsh bool `mapstructure:"use_pwsh"` + // Whether to run PowerShell in non-interactive mode. + // Defaults to true. + NonInteractive *bool `mapstructure:"non_interactive"` + ctx interpolate.Context } @@ -129,15 +133,19 @@ type Provisioner struct { } func (p *Provisioner) defaultExecuteCommand() string { + nonInteractive := "" + if *p.config.NonInteractive { + nonInteractive = "-NonInteractive " + } if p.config.ExecutionPolicy == ExecutionPolicyNone { - return `-file {{.Path}}` + return fmt.Sprintf(`%s-file {{.Path}}`, nonInteractive) } if p.config.UsePwsh { - return fmt.Sprintf(`pwsh -executionpolicy %s -file {{.Path}}`, p.config.ExecutionPolicy) + return fmt.Sprintf(`pwsh %s-executionpolicy %s -file {{.Path}}`, nonInteractive, p.config.ExecutionPolicy) } else { - return fmt.Sprintf(`powershell -executionpolicy %s -file {{.Path}}`, p.config.ExecutionPolicy) + return fmt.Sprintf(`powershell %s-executionpolicy %s -file {{.Path}}`, nonInteractive, p.config.ExecutionPolicy) } } @@ -152,14 +160,19 @@ func (p *Provisioner) defaultScriptCommand() string { baseCmd += `. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }` + nonInteractive := "" + if *p.config.NonInteractive { + nonInteractive = "-NonInteractive " + } + if p.config.ExecutionPolicy == ExecutionPolicyNone { - return baseCmd + return fmt.Sprintf(`%s-command "%s"`, nonInteractive, baseCmd) } if p.config.UsePwsh { - return fmt.Sprintf(`pwsh -executionpolicy %s -command "%s"`, p.config.ExecutionPolicy, baseCmd) + return fmt.Sprintf(`pwsh %s-executionpolicy %s -command "%s"`, nonInteractive, p.config.ExecutionPolicy, baseCmd) } else { - return fmt.Sprintf(`powershell -executionpolicy %s "%s"`, p.config.ExecutionPolicy, baseCmd) + return fmt.Sprintf(`powershell %s-executionpolicy %s "%s"`, nonInteractive, p.config.ExecutionPolicy, baseCmd) } } @@ -196,6 +209,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.Inline = nil } + if p.config.NonInteractive == nil { + b := true + p.config.NonInteractive = &b + } + if p.config.StartRetryTimeout == 0 { p.config.StartRetryTimeout = 5 * time.Minute } diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index 9ea318a37..47181bc81 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -77,12 +77,12 @@ func TestProvisionerPrepare_Defaults(t *testing.T) { t.Error("expected elevated_password to be empty") } - if p.config.ExecuteCommand != `powershell -executionpolicy bypass -file {{.Path}}` { - t.Fatalf(`Default command should be 'powershell -executionpolicy bypass -file {{.Path}}', but got '%s'`, p.config.ExecuteCommand) + if p.config.ExecuteCommand != `powershell -NonInteractive -executionpolicy bypass -file {{.Path}}` { + t.Fatalf(`Default command should be 'powershell -NonInteractive -executionpolicy bypass -file {{.Path}}', but got '%s'`, p.config.ExecuteCommand) } - if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass -file {{.Path}}` { - t.Fatalf(`Default command should be 'powershell -executionpolicy bypass -file {{.Path}}', but got '%s'`, p.config.ElevatedExecuteCommand) + if p.config.ElevatedExecuteCommand != `powershell -NonInteractive -executionpolicy bypass -file {{.Path}}` { + t.Fatalf(`Default command should be 'powershell -NonInteractive -executionpolicy bypass -file {{.Path}}', but got '%s'`, p.config.ElevatedExecuteCommand) } if p.config.ElevatedEnvVarFormat != `$env:%s="%s"; ` { @@ -123,7 +123,7 @@ func TestProvisionerPrepare_DebugMode(t *testing.T) { t.Fatalf("err: %s", err) } - command := `powershell -executionpolicy bypass -file {{.Path}}` + command := `powershell -NonInteractive -executionpolicy bypass -file {{.Path}}` if p.config.ExecuteCommand != command { t.Fatalf(`Expected command should be '%s' but got '%s'`, command, p.config.ExecuteCommand) } @@ -486,7 +486,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { } cmd := comm.StartCmd.Command - re := regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/inlineScript.ps1`) + re := regexp.MustCompile(`powershell -NonInteractive -executionpolicy bypass -file c:/Windows/Temp/inlineScript.ps1`) matched := re.MatchString(cmd) if !matched { @@ -507,7 +507,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { } cmd = comm.StartCmd.Command - re = regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/inlineScript.ps1`) + re = regexp.MustCompile(`powershell -NonInteractive -executionpolicy bypass -file c:/Windows/Temp/inlineScript.ps1`) matched = re.MatchString(cmd) if !matched { t.Fatalf("Got unexpected command: %s", cmd) @@ -537,7 +537,7 @@ func TestProvisionerProvision_Scripts(t *testing.T) { } cmd := comm.StartCmd.Command - re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`) + re := regexp.MustCompile(`powershell -NonInteractive -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`) matched := re.MatchString(cmd) if !matched { t.Fatalf("Got unexpected command: %s", cmd) @@ -574,7 +574,7 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) { } cmd := comm.StartCmd.Command - re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`) + re := regexp.MustCompile(`powershell -NonInteractive -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`) matched := re.MatchString(cmd) if !matched { t.Fatalf("Got unexpected command: %s", cmd) @@ -599,11 +599,11 @@ func TestProvisionerProvision_SkipClean(t *testing.T) { }{ { SkipClean: true, - LastExecutedCommandRegex: `powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`, + LastExecutedCommandRegex: `powershell -NonInteractive -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`, }, { SkipClean: false, - LastExecutedCommandRegex: `powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/packer-cleanup-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1'; exit \$LastExitCode }"`, + LastExecutedCommandRegex: `powershell -NonInteractive -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/packer-cleanup-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1'; exit \$LastExitCode }"`, }, } @@ -921,7 +921,7 @@ func TestProvision_createCommandText(t *testing.T) { p.generatedData = make(map[string]interface{}) cmd, _ := p.createCommandText() - re := regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/script.ps1`) + re := regexp.MustCompile(`powershell -NonInteractive -executionpolicy bypass -file c:/Windows/Temp/script.ps1`) matched := re.MatchString(cmd) if !matched { t.Fatalf("Got unexpected command: %s", cmd) @@ -931,7 +931,7 @@ func TestProvision_createCommandText(t *testing.T) { p.config.ElevatedUser = "vagrant" p.config.ElevatedPassword = "vagrant" cmd, _ = p.createCommandText() - re = regexp.MustCompile(`powershell -executionpolicy bypass -file "C:/Windows/Temp/packer-elevated-shell-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1"`) + re = regexp.MustCompile(`powershell -NonInteractive -executionpolicy bypass -file "C:/Windows/Temp/packer-elevated-shell-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1"`) matched = re.MatchString(cmd) if !matched { t.Fatalf("Got unexpected elevated command: %s", cmd)