provisioner/powershell: Update default execute command to handle script errors
This change sets the ErrorActionPreference and wraps the script execution in a Try/Catch statement so that the provisioner can capture any errors encountered when running the script. In addition to the try/catch the `&` operator is replaced by the `.` sourcing operator to ensure the script is executed in the same scope as the parent command (so that errors bubble up properly). Tests after change ``` ⇶ ACC_TEST_BUILDERS=amazon-ebs ACC_TEST_PROVISIONERS=powershell go test ./provisioner/powershell/... -timeout=1h ok github.com/hashicorp/packer/provisioner/powershell 915.865s ```
This commit is contained in:
parent
13e0c1a097
commit
35df3914d2
|
@ -98,13 +98,15 @@ type Provisioner struct {
|
|||
|
||||
func (p *Provisioner) defaultExecuteCommand() string {
|
||||
baseCmd := `& { if (Test-Path variable:global:ProgressPreference)` +
|
||||
`{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};`
|
||||
`{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};` +
|
||||
`{set-variable -name variable:global:ErrorActionPreference -value 'Continue'};` +
|
||||
`%s. {{.Vars}};try { . '{{.Path}}' } catch { Write-Error $Error[0]; exit 1 }; exit $LastExitCode }`
|
||||
|
||||
var debugLine string
|
||||
if p.config.DebugMode != 0 {
|
||||
baseCmd += fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode)
|
||||
debugLine = fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode)
|
||||
}
|
||||
|
||||
baseCmd += `. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }`
|
||||
baseCmd = fmt.Sprintf(baseCmd, debugLine)
|
||||
|
||||
if p.config.ExecutionPolicy == ExecutionPolicyNone {
|
||||
return baseCmd
|
||||
|
|
|
@ -39,10 +39,10 @@ func TestAccPowershellProvisioner_Script(t *testing.T) {
|
|||
acc.TestProvisionersAgainstBuilders(&testProvisioner, t)
|
||||
}
|
||||
|
||||
func TestPowershellProvisioner_Invalid(t *testing.T) {
|
||||
func TestAccPowershellProvisioner_Invalid(t *testing.T) {
|
||||
acc.TestProvisionersPreCheck(TestProvisionerName, t)
|
||||
|
||||
// This test should fail with a non-zero exit code. To assert the failure the fixture
|
||||
// This provisioner should fail with an exit code of 1. To assert the failure the fixture
|
||||
// uses the valid_exit_codes option to confirm a non-zero exit code
|
||||
testProvisioner := PowershellProvisionerAccTest{"powershell-provisioner-invalid.txt"}
|
||||
acc.TestProvisionersAgainstBuilders(&testProvisioner, t)
|
||||
|
|
|
@ -71,12 +71,13 @@ func TestProvisionerPrepare_Defaults(t *testing.T) {
|
|||
t.Error("expected elevated_password to be empty")
|
||||
}
|
||||
|
||||
if p.config.ExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
|
||||
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ExecuteCommand)
|
||||
if p.config.ExecuteCommand != executeCommand(`. {{.Vars}}`, `{{.Path}}`) {
|
||||
t.Fatalf(`Default command should be %s, but got '%s'`, executeCommand(`. {{.Vars}}`, ` {{.Path}}`), p.config.ExecuteCommand)
|
||||
}
|
||||
|
||||
if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
|
||||
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ElevatedExecuteCommand)
|
||||
if p.config.ElevatedExecuteCommand != executeCommand(`. {{.Vars}}`, `{{.Path}}`) {
|
||||
t.Fatalf(`Default command should be %s, but got '%s'`, executeCommand(`. {{.Vars}}`, `{{.Path}}`), p.config.ElevatedExecuteCommand)
|
||||
|
||||
}
|
||||
|
||||
if p.config.ElevatedEnvVarFormat != `$env:%s="%s"; ` {
|
||||
|
@ -117,7 +118,7 @@ func TestProvisionerPrepare_DebugMode(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
command := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};Set-PsDebug -Trace 1;. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
|
||||
command := executeCommand(`Set-PsDebug -Trace 1;. {{.Vars}}`, `{{.Path}}`)
|
||||
if p.config.ExecuteCommand != command {
|
||||
t.Fatalf(fmt.Sprintf(`Expected command should be '%s' but got '%s'`, command, p.config.ExecuteCommand))
|
||||
}
|
||||
|
@ -426,7 +427,7 @@ func TestProvisionerProvision_Inline(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/inlineScript.ps1'; exit \$LastExitCode }"`)
|
||||
re := regexp.MustCompile(`\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/inlineScript\.ps1' }`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
@ -446,7 +447,7 @@ func TestProvisionerProvision_Inline(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/inlineScript.ps1'; exit \$LastExitCode }"`)
|
||||
re = regexp.MustCompile(`\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/inlineScript\.ps1' }`)
|
||||
matched = re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
@ -476,7 +477,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(`\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/script\.ps1' }`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
@ -513,7 +514,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(`\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/script\.ps1' }`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
@ -538,11 +539,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: `\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/script.ps1' }`,
|
||||
},
|
||||
{
|
||||
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: `\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/packer-cleanup-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1' }`,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -802,7 +803,7 @@ func TestProvision_createCommandText(t *testing.T) {
|
|||
p.generatedData = make(map[string]interface{})
|
||||
cmd, _ := p.createCommandText()
|
||||
|
||||
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(`\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1;try { \. 'c:/Windows/Temp/script\.ps1' }`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
@ -861,3 +862,7 @@ func generatedData() map[string]interface{} {
|
|||
"PackerHTTPPort": common.HttpPortNotImplemented,
|
||||
}
|
||||
}
|
||||
|
||||
func executeCommand(varsStr, pathStr string) string {
|
||||
return fmt.Sprintf(`powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};{set-variable -name variable:global:ErrorActionPreference -value 'Continue'};%s;try { . '%s' } catch { Write-Error $Error[0]; exit 1 }; exit $LastExitCode }"`, varsStr, pathStr)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"type": "powershell",
|
||||
"inline": "this is not a valid powershell command",
|
||||
"inline": ["invalid-cmdlet"],
|
||||
"valid_exit_codes": ["1"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue