From 13e0c1a097820829d7f9f53d6b977abfc9551584 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Thu, 9 Apr 2020 05:03:56 -0400 Subject: [PATCH 1/4] tests/provisioner/powershell: Add acceptance test to reproduce issue 4916 --- provisioner/powershell/provisioner_acc_test.go | 9 +++++++++ .../test-fixtures/powershell-provisioner-invalid.txt | 5 +++++ 2 files changed, 14 insertions(+) create mode 100644 provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt diff --git a/provisioner/powershell/provisioner_acc_test.go b/provisioner/powershell/provisioner_acc_test.go index 846ab0c3d..4a471082e 100644 --- a/provisioner/powershell/provisioner_acc_test.go +++ b/provisioner/powershell/provisioner_acc_test.go @@ -39,6 +39,15 @@ func TestAccPowershellProvisioner_Script(t *testing.T) { acc.TestProvisionersAgainstBuilders(&testProvisioner, t) } +func TestPowershellProvisioner_Invalid(t *testing.T) { + acc.TestProvisionersPreCheck(TestProvisionerName, t) + + // This test should fail with a non-zero exit code. 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) +} + type PowershellProvisionerAccTest struct { ConfigName string } diff --git a/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt b/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt new file mode 100644 index 000000000..836d9c5cf --- /dev/null +++ b/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt @@ -0,0 +1,5 @@ +{ + "type": "powershell", + "inline": "this is not a valid powershell command", + "valid_exit_codes": ["1"] +} From 35df3914d2079ca4ee56df1e2f96c8507f0d6499 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Fri, 10 Apr 2020 07:12:32 -0400 Subject: [PATCH 2/4] provisioner/powershell: Update default execute command to handle script errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 ``` --- provisioner/powershell/provisioner.go | 10 ++++--- .../powershell/provisioner_acc_test.go | 4 +-- provisioner/powershell/provisioner_test.go | 29 +++++++++++-------- .../powershell-provisioner-invalid.txt | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 6659de8dc..4dc8486ec 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -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 diff --git a/provisioner/powershell/provisioner_acc_test.go b/provisioner/powershell/provisioner_acc_test.go index 4a471082e..848ae04c8 100644 --- a/provisioner/powershell/provisioner_acc_test.go +++ b/provisioner/powershell/provisioner_acc_test.go @@ -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) diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index 4def2785c..d120c0eb8 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -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) +} diff --git a/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt b/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt index 836d9c5cf..037cb5551 100644 --- a/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt +++ b/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt @@ -1,5 +1,5 @@ { "type": "powershell", - "inline": "this is not a valid powershell command", + "inline": ["invalid-cmdlet"], "valid_exit_codes": ["1"] } From 38f799df3e81ec8188921c445b9f627f0d242543 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Mon, 4 May 2020 13:52:34 -0400 Subject: [PATCH 3/4] Add conditional to check if LastExitCode is defined * Add broken requires statement test case * Add test case to reproduce invalid LastExitCode --- provisioner/powershell/provisioner.go | 2 +- .../powershell/provisioner_acc_test.go | 2 +- .../powershell-exit_codes-provisioner.txt | 19 +++++++++++++++++++ .../powershell-provisioner-invalid.txt | 5 ----- .../scripts/set_version_latest.ps1 | 19 +++++++++++++++++++ 5 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt delete mode 100644 provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt create mode 100644 provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 4dc8486ec..9b3e30ef7 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -100,7 +100,7 @@ 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:ErrorActionPreference -value 'Continue'};` + - `%s. {{.Vars}};try { . '{{.Path}}' } catch { Write-Error $Error[0]; exit 1 }; exit $LastExitCode }` + `%s. {{.Vars}};try { & '{{.Path}}' } catch { Write-Error $Error[0]; exit 1 }; if ($LastExitCode) { exit $LastExitCode }}` var debugLine string if p.config.DebugMode != 0 { diff --git a/provisioner/powershell/provisioner_acc_test.go b/provisioner/powershell/provisioner_acc_test.go index 848ae04c8..bd96cddf7 100644 --- a/provisioner/powershell/provisioner_acc_test.go +++ b/provisioner/powershell/provisioner_acc_test.go @@ -44,7 +44,7 @@ func TestAccPowershellProvisioner_Invalid(t *testing.T) { // 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"} + testProvisioner := PowershellProvisionerAccTest{"powershell-exit_codes-provisioner.txt"} acc.TestProvisionersAgainstBuilders(&testProvisioner, t) } diff --git a/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt b/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt new file mode 100644 index 000000000..a8bfca090 --- /dev/null +++ b/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt @@ -0,0 +1,19 @@ +{ + "type": "powershell", + "inline": ["invalid-cmdlet"], + "valid_exit_codes": ["1"] +}, +{ + "type": "powershell", + "inline": ["#Requires -Version 10.0"], + "valid_exit_codes": ["1"] +}, +{ + "type": "powershell", + "script": "../../provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1" +}, +{ + "type": "powershell", + "inline": "sc.exe start Life", + "valid_exit_codes": ["1060"] +} diff --git a/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt b/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt deleted file mode 100644 index 037cb5551..000000000 --- a/provisioner/powershell/test-fixtures/powershell-provisioner-invalid.txt +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "powershell", - "inline": ["invalid-cmdlet"], - "valid_exit_codes": ["1"] -} diff --git a/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 b/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 new file mode 100644 index 000000000..a8bbfff22 --- /dev/null +++ b/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 @@ -0,0 +1,19 @@ +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +function test +{ + + $myNumbersCollection = 1..5 + + if($myNumbersCollection -contains 3) + { + "collection contains 3" + } + else + { + "collection doesn't contain 3" + } +} + +test From 2e326ef334d36ebaeadba72987b220229e246bb8 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Wed, 20 May 2020 15:25:19 -0400 Subject: [PATCH 4/4] Switch back to call operator as opposed to dot sourcing * Ensure child scope doesn't conflict with parent scope * Add elevated user options to tests case. --- provisioner/powershell/provisioner.go | 8 +++---- .../powershell/provisioner_acc_test.go | 2 +- provisioner/powershell/provisioner_test.go | 16 +++++++------- .../powershell-exit_codes-provisioner.txt | 10 ++++++++- .../scripts/set_version_latest.ps1 | 22 +++++++------------ 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 9b3e30ef7..ab1fbe820 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -99,14 +99,12 @@ 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:ErrorActionPreference -value 'Continue'};` + - `%s. {{.Vars}};try { & '{{.Path}}' } catch { Write-Error $Error[0]; exit 1 }; if ($LastExitCode) { exit $LastExitCode }}` + `{set-variable -name variable:global:ErrorActionPreference -value 'Continue'};` - var debugLine string if p.config.DebugMode != 0 { - debugLine = fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode) + baseCmd += fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode) } - baseCmd = fmt.Sprintf(baseCmd, debugLine) + baseCmd += `. {{.Vars}};try { & '{{.Path}}' } catch { Write-Error $Error[0]; exit 1 }; if ($LastExitCode) { exit $LastExitCode }}` if p.config.ExecutionPolicy == ExecutionPolicyNone { return baseCmd diff --git a/provisioner/powershell/provisioner_acc_test.go b/provisioner/powershell/provisioner_acc_test.go index bd96cddf7..3a5cbef75 100644 --- a/provisioner/powershell/provisioner_acc_test.go +++ b/provisioner/powershell/provisioner_acc_test.go @@ -39,7 +39,7 @@ func TestAccPowershellProvisioner_Script(t *testing.T) { acc.TestProvisionersAgainstBuilders(&testProvisioner, t) } -func TestAccPowershellProvisioner_Invalid(t *testing.T) { +func TestAccPowershellProvisioner_ExitCodes(t *testing.T) { acc.TestProvisionersPreCheck(TestProvisionerName, t) // This provisioner should fail with an exit code of 1. To assert the failure the fixture diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index d120c0eb8..0b66e186c 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -427,7 +427,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { } cmd := comm.StartCmd.Command - 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' }`) + 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) @@ -447,7 +447,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { } cmd = comm.StartCmd.Command - 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' }`) + 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) @@ -477,7 +477,7 @@ func TestProvisionerProvision_Scripts(t *testing.T) { } cmd := comm.StartCmd.Command - 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' }`) + 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) @@ -514,7 +514,7 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) { } cmd := comm.StartCmd.Command - 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' }`) + 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) @@ -539,11 +539,11 @@ func TestProvisionerProvision_SkipClean(t *testing.T) { }{ { SkipClean: true, - 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' }`, + 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: `\. 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' }`, + 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' }`, }, } @@ -803,7 +803,7 @@ func TestProvision_createCommandText(t *testing.T) { p.generatedData = make(map[string]interface{}) cmd, _ := p.createCommandText() - 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' }`) + 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) @@ -864,5 +864,5 @@ func generatedData() map[string]interface{} { } 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) + 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 }; if ($LastExitCode) { exit $LastExitCode }}"`, varsStr, pathStr) } diff --git a/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt b/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt index a8bfca090..fd2e42860 100644 --- a/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt +++ b/provisioner/powershell/test-fixtures/powershell-exit_codes-provisioner.txt @@ -10,7 +10,15 @@ }, { "type": "powershell", - "script": "../../provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1" + "script": "../../provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1", + "valid_exit_codes": ["0"] +}, +{ + "type": "powershell", + "elevated_user": "Administrator", + "elevated_password": "{{.WinRMPassword}}", + "inline": "Get-ItemProperty -Path HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion", + "valid_exit_codes": ["0"] }, { "type": "powershell", diff --git a/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 b/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 index a8bbfff22..4d05fd5f7 100644 --- a/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 +++ b/provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1 @@ -1,19 +1,13 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" -function test -{ - - $myNumbersCollection = 1..5 +$myNumbersCollection = 1..5 - if($myNumbersCollection -contains 3) - { - "collection contains 3" - } - else - { - "collection doesn't contain 3" - } +if($myNumbersCollection -contains 3) +{ + "collection contains 3" +} +else +{ + "collection doesn't contain 3" } - -test