Compare commits
6 Commits
master
...
b-powershe
Author | SHA1 | Date | |
---|---|---|---|
|
8de1eddcb2 | ||
|
9df4129d6d | ||
|
ab93bc8a5d | ||
|
e90913fcd2 | ||
|
b1fec8f0bc | ||
|
ed1a2b1deb |
@ -9,6 +9,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -37,6 +38,43 @@ var psEscape = strings.NewReplacer(
|
||||
"'", "`'",
|
||||
)
|
||||
|
||||
const PowershellWrapperScript string = `
|
||||
if (Test-Path variable:global:ProgressPreference) {
|
||||
set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'
|
||||
}
|
||||
set-variable -name variable:global:ErrorActionPreference -value 'Continue'
|
||||
$global:LASTEXITCODE = 0
|
||||
$global:lastcmdlet = $null
|
||||
trap [Exception] {write-error ($_.Exception.Message);exit 1}
|
||||
|
||||
{{if .DebugMode}}
|
||||
Set-PsDebug -Trace {{.DebugMode}}
|
||||
{{- end}}
|
||||
|
||||
{{.Vars}}
|
||||
|
||||
$results = {
|
||||
|
||||
{{.Payload}}
|
||||
|
||||
$global:lastcmdlet = $?
|
||||
}.invokereturnasis()
|
||||
|
||||
$exitstatus = 1
|
||||
|
||||
if ($lastcmdlet) {
|
||||
$exitstatus = 0
|
||||
}
|
||||
|
||||
if ( $LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0 ) {
|
||||
$exitstatus = $LASTEXITCODE
|
||||
}
|
||||
|
||||
Write-Host $results
|
||||
|
||||
exit $exitstatus
|
||||
`
|
||||
|
||||
type Config struct {
|
||||
shell.Provisioner `mapstructure:",squash"`
|
||||
|
||||
@ -76,8 +114,6 @@ type Config struct {
|
||||
|
||||
ExecutionPolicy ExecutionPolicy `mapstructure:"execution_policy"`
|
||||
|
||||
remoteCleanUpScriptPath string
|
||||
|
||||
// If set, sets PowerShell's [PSDebug mode](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-psdebug?view=powershell-7)
|
||||
// in order to make script debugging easier. For instance, setting the
|
||||
// value to 1 results in adding this to the execute command:
|
||||
@ -87,30 +123,30 @@ type Config struct {
|
||||
// ```
|
||||
DebugMode int `mapstructure:"debug_mode"`
|
||||
|
||||
// If set, any Powershell provided `Inline` command(s) or `Script(s)` will
|
||||
// get wrapped in a Packer error handling script to help with capturing
|
||||
// non-zero exit codes or unexpected failures. Defaults to true.
|
||||
// It is explicitly to false when using a custom ExecuteCommand or ElevatedExecuteCommand.
|
||||
UseErrorWrapperScript bool `mapstructure:"use_error_wrapper"`
|
||||
|
||||
remoteCleanUpScriptPath string
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
type Provisioner struct {
|
||||
config Config
|
||||
communicator packer.Communicator
|
||||
generatedData map[string]interface{}
|
||||
config Config
|
||||
communicator packer.Communicator
|
||||
generatedData map[string]interface{}
|
||||
useWrappedCommmand bool
|
||||
}
|
||||
|
||||
func (p *Provisioner) defaultExecuteCommand() string {
|
||||
baseCmd := `& { if (Test-Path variable:global:ProgressPreference)` +
|
||||
`{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};`
|
||||
|
||||
if p.config.DebugMode != 0 {
|
||||
baseCmd += fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode)
|
||||
}
|
||||
|
||||
baseCmd += `. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }`
|
||||
|
||||
if p.config.ExecutionPolicy == ExecutionPolicyNone {
|
||||
return baseCmd
|
||||
return `-file {{.Path}}`
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`powershell -executionpolicy %s "%s"`, p.config.ExecutionPolicy, baseCmd)
|
||||
return fmt.Sprintf(`powershell -noninteractive -noprofile -executionpolicy %s -file {{.Path}}`, p.config.ExecutionPolicy)
|
||||
}
|
||||
|
||||
func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
@ -132,6 +168,9 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set Remote execution defaults
|
||||
p.config.remoteCleanUpScriptPath = fmt.Sprintf(`c:/Windows/Temp/packer-cleanup-%s.ps1`, uuid.TimeOrderedUUID())
|
||||
|
||||
if p.config.EnvVarFormat == "" {
|
||||
p.config.EnvVarFormat = `$env:%s="%s"; `
|
||||
}
|
||||
@ -142,10 +181,12 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
|
||||
if p.config.ExecuteCommand == "" {
|
||||
p.config.ExecuteCommand = p.defaultExecuteCommand()
|
||||
p.config.UseErrorWrapperScript = true
|
||||
}
|
||||
|
||||
if p.config.ElevatedExecuteCommand == "" {
|
||||
p.config.ElevatedExecuteCommand = p.defaultExecuteCommand()
|
||||
p.config.UseErrorWrapperScript = true
|
||||
}
|
||||
|
||||
if p.config.Inline != nil && len(p.config.Inline) == 0 {
|
||||
@ -157,13 +198,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
}
|
||||
|
||||
if p.config.RemotePath == "" {
|
||||
uuid := uuid.TimeOrderedUUID()
|
||||
p.config.RemotePath = fmt.Sprintf(`c:/Windows/Temp/script-%s.ps1`, uuid)
|
||||
p.config.RemotePath = fmt.Sprintf(`c:/Windows/Temp/script-%s.ps1`, uuid.TimeOrderedUUID())
|
||||
}
|
||||
|
||||
if p.config.RemoteEnvVarPath == "" {
|
||||
uuid := uuid.TimeOrderedUUID()
|
||||
p.config.RemoteEnvVarPath = fmt.Sprintf(`c:/Windows/Temp/packer-ps-env-vars-%s.ps1`, uuid)
|
||||
p.config.RemoteEnvVarPath = fmt.Sprintf(`c:/Windows/Temp/packer-ps-env-vars-%s.ps1`, uuid.TimeOrderedUUID())
|
||||
}
|
||||
|
||||
if p.config.Scripts == nil {
|
||||
@ -174,8 +213,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
p.config.Vars = make([]string, 0)
|
||||
}
|
||||
|
||||
p.config.remoteCleanUpScriptPath = fmt.Sprintf(`c:/Windows/Temp/packer-cleanup-%s.ps1`, uuid.TimeOrderedUUID())
|
||||
|
||||
// Validate parsed configuration data
|
||||
var errs error
|
||||
if p.config.Script != "" && len(p.config.Scripts) > 0 {
|
||||
errs = packer.MultiErrorAppend(errs,
|
||||
@ -223,37 +261,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
}
|
||||
|
||||
if !(p.config.DebugMode >= 0 && p.config.DebugMode <= 2) {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("%d is an invalid Trace level for `debug_mode`; valid values are 0, 1, and 2", p.config.DebugMode))
|
||||
s := "%d is an invalid Trace level for `debug_mode`; valid values are 0, 1, and 2"
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf(s, p.config.DebugMode))
|
||||
}
|
||||
|
||||
if errs != nil {
|
||||
return errs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Takes the inline scripts, concatenates them into a temporary file and
|
||||
// returns a string containing the location of said file.
|
||||
func extractScript(p *Provisioner) (string, error) {
|
||||
temp, err := tmp.File("powershell-provisioner")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer temp.Close()
|
||||
writer := bufio.NewWriter(temp)
|
||||
for _, command := range p.config.Inline {
|
||||
log.Printf("Found command: %s", command)
|
||||
if _, err := writer.WriteString(command + "\n"); err != nil {
|
||||
return "", fmt.Errorf("Error preparing powershell script: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := writer.Flush(); err != nil {
|
||||
return "", fmt.Errorf("Error preparing powershell script: %s", err)
|
||||
}
|
||||
|
||||
return temp.Name(), nil
|
||||
return errs
|
||||
}
|
||||
|
||||
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error {
|
||||
@ -284,17 +296,26 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error stating powershell script: %s", err)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(p.config.RemotePath, `\`) {
|
||||
// path is a directory
|
||||
p.config.RemotePath += filepath.Base((fi).Name())
|
||||
}
|
||||
f, err := os.Open(path)
|
||||
|
||||
payload, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error opening powershell script: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
command, err := p.createCommandText()
|
||||
data := string(payload)
|
||||
if p.config.UseErrorWrapperScript {
|
||||
data, err = p.WrapScriptContents(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
command, err := p.buildInterpolatedCommand()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
@ -305,10 +326,8 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C
|
||||
// command is executed but the file doesn't exist any longer.
|
||||
var cmd *packer.RemoteCmd
|
||||
err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
|
||||
if _, err := f.Seek(0, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := comm.Upload(p.config.RemotePath, f, &fi); err != nil {
|
||||
|
||||
if err := comm.Upload(p.config.RemotePath, strings.NewReader(data), nil); err != nil {
|
||||
return fmt.Errorf("Error uploading script: %s", err)
|
||||
}
|
||||
|
||||
@ -319,9 +338,6 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C
|
||||
return err
|
||||
}
|
||||
|
||||
// Close the original file since we copied it
|
||||
f.Close()
|
||||
|
||||
// Record every other uploaded script file so we can clean it up later
|
||||
uploadedScripts = append(uploadedScripts, p.config.RemotePath)
|
||||
|
||||
@ -371,13 +387,119 @@ func (p *Provisioner) createRemoteCleanUpCommand(remoteFiles []string) (string,
|
||||
return "", fmt.Errorf("clean up script %q failed to upload: %s", remotePath, err)
|
||||
}
|
||||
|
||||
data := p.generatedData
|
||||
data["Path"] = remotePath
|
||||
data["Vars"] = p.config.RemoteEnvVarPath
|
||||
p.config.ctx.Data = data
|
||||
ctxData := p.generatedData
|
||||
ctxData["Path"] = remotePath
|
||||
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
|
||||
p.config.ctx.Data = data
|
||||
return interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
// Return the interpolated command
|
||||
return command, nil
|
||||
}
|
||||
|
||||
// buildInterpolatedCommand returns the actual command to be executed at runtime.
|
||||
func (p *Provisioner) buildInterpolatedCommand() (string, error) {
|
||||
if p.config.ElevatedUser != "" {
|
||||
return p.elevatedExecuteCommand()
|
||||
}
|
||||
|
||||
return p.executeCommand()
|
||||
}
|
||||
|
||||
// WrapScriptContents will generate a Powershell wrapper for executing p.config.Inline or p.config.Scripts
|
||||
func (p *Provisioner) WrapScriptContents(payload []byte) (string, error) {
|
||||
|
||||
var b strings.Builder
|
||||
if _, err := b.Write(payload); err != nil {
|
||||
return "", fmt.Errorf("failed to wrap script contents: %s", err)
|
||||
}
|
||||
|
||||
ctxData := p.generatedData
|
||||
ctxData["Vars"] = p.createFlattenedEnvVars(p.config.ElevatedUser != "")
|
||||
ctxData["Payload"] = b.String()
|
||||
ctxData["DebugMode"] = p.config.DebugMode
|
||||
p.config.ctx.Data = ctxData
|
||||
|
||||
data, err := interpolate.Render(PowershellWrapperScript, &p.config.ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error building powershell wrapper: %s", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (p *Provisioner) executeCommand() (string, error) {
|
||||
|
||||
// Prepare everything needed to enable the required env vars within the
|
||||
// remote environment
|
||||
err := p.prepareEnvVars(false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctxData := p.generatedData
|
||||
ctxData["Path"] = p.config.RemotePath
|
||||
ctxData["Vars"] = p.config.RemoteEnvVarPath
|
||||
p.config.ctx.Data = ctxData
|
||||
|
||||
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
|
||||
// Return the interpolated command
|
||||
return command, nil
|
||||
}
|
||||
|
||||
func (p *Provisioner) elevatedExecuteCommand() (command string, err error) {
|
||||
|
||||
// Prepare everything needed to enable the required env vars within the
|
||||
// remote environment
|
||||
err = p.prepareEnvVars(true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ctxData := p.generatedData
|
||||
ctxData["Path"] = p.config.RemotePath
|
||||
ctxData["Vars"] = p.config.RemoteEnvVarPath
|
||||
p.config.ctx.Data = ctxData
|
||||
|
||||
command, err = interpolate.Render(p.config.ElevatedExecuteCommand, &p.config.ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
|
||||
command, err = provisioner.GenerateElevatedRunner(command, p)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating elevated runner: %s", err)
|
||||
}
|
||||
|
||||
return command, err
|
||||
}
|
||||
|
||||
// Takes the inline scripts, concatenates them into a temporary file and
|
||||
// returns a string containing the location of said file.
|
||||
func extractScript(p *Provisioner) (string, error) {
|
||||
temp, err := tmp.File("powershell-provisioner")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer temp.Close()
|
||||
writer := bufio.NewWriter(temp)
|
||||
for _, command := range p.config.Inline {
|
||||
log.Printf("Found command: %s", command)
|
||||
if _, err := writer.WriteString(command + "\n"); err != nil {
|
||||
return "", fmt.Errorf("Error preparing powershell script: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := writer.Flush(); err != nil {
|
||||
return "", fmt.Errorf("Error preparing powershell script: %s", err)
|
||||
}
|
||||
|
||||
return temp.Name(), nil
|
||||
}
|
||||
|
||||
// Environment variables required within the remote environment are uploaded
|
||||
@ -472,63 +594,6 @@ func (p *Provisioner) uploadEnvVars(flattenedEnvVars string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Provisioner) createCommandText() (command string, err error) {
|
||||
// Return the interpolated command
|
||||
if p.config.ElevatedUser == "" {
|
||||
return p.createCommandTextNonPrivileged()
|
||||
} else {
|
||||
return p.createCommandTextPrivileged()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provisioner) createCommandTextNonPrivileged() (command string, err error) {
|
||||
// Prepare everything needed to enable the required env vars within the
|
||||
// remote environment
|
||||
err = p.prepareEnvVars(false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctxData := p.generatedData
|
||||
ctxData["Path"] = p.config.RemotePath
|
||||
ctxData["Vars"] = p.config.RemoteEnvVarPath
|
||||
p.config.ctx.Data = ctxData
|
||||
|
||||
command, err = interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
|
||||
// Return the interpolated command
|
||||
return command, nil
|
||||
}
|
||||
|
||||
func (p *Provisioner) createCommandTextPrivileged() (command string, err error) {
|
||||
// Prepare everything needed to enable the required env vars within the
|
||||
// remote environment
|
||||
err = p.prepareEnvVars(true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ctxData := p.generatedData
|
||||
ctxData["Path"] = p.config.RemotePath
|
||||
ctxData["Vars"] = p.config.RemoteEnvVarPath
|
||||
p.config.ctx.Data = ctxData
|
||||
|
||||
command, err = interpolate.Render(p.config.ElevatedExecuteCommand, &p.config.ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
|
||||
command, err = provisioner.GenerateElevatedRunner(command, p)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating elevated runner: %s", err)
|
||||
}
|
||||
|
||||
return command, err
|
||||
}
|
||||
|
||||
func (p *Provisioner) Communicator() packer.Communicator {
|
||||
return p.communicator
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ type FlatConfig struct {
|
||||
ElevatedPassword *string `mapstructure:"elevated_password" cty:"elevated_password" hcl:"elevated_password"`
|
||||
ExecutionPolicy *string `mapstructure:"execution_policy" cty:"execution_policy" hcl:"execution_policy"`
|
||||
DebugMode *int `mapstructure:"debug_mode" cty:"debug_mode" hcl:"debug_mode"`
|
||||
UseErrorWrapperScript *bool `mapstructure:"use_error_wrapper" cty:"use_error_wrapper" hcl:"use_error_wrapper"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@ -73,6 +74,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"elevated_password": &hcldec.AttrSpec{Name: "elevated_password", Type: cty.String, Required: false},
|
||||
"execution_policy": &hcldec.AttrSpec{Name: "execution_policy", Type: cty.String, Required: false},
|
||||
"debug_mode": &hcldec.AttrSpec{Name: "debug_mode", Type: cty.Number, Required: false},
|
||||
"use_error_wrapper": &hcldec.AttrSpec{Name: "use_error_wrapper", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -39,6 +39,15 @@ func TestAccPowershellProvisioner_Script(t *testing.T) {
|
||||
acc.TestProvisionersAgainstBuilders(&testProvisioner, 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
|
||||
// uses the valid_exit_codes option to confirm a non-zero exit code
|
||||
testProvisioner := PowershellProvisionerAccTest{"powershell-exit_codes-provisioner.txt"}
|
||||
acc.TestProvisionersAgainstBuilders(&testProvisioner, t)
|
||||
}
|
||||
|
||||
type PowershellProvisionerAccTest struct {
|
||||
ConfigName string
|
||||
}
|
||||
|
@ -71,6 +71,44 @@ func TestProvisionerPrepare_Defaults(t *testing.T) {
|
||||
t.Error("expected elevated_password to be empty")
|
||||
}
|
||||
|
||||
matched, _ = regexp.MatchString("powershell -noninteractive -noprofile -executionpolicy bypass -file {{.Path}}", p.config.ExecuteCommand)
|
||||
if !matched {
|
||||
t.Errorf("expected default execute command, but got : %s", p.config.ExecuteCommand)
|
||||
}
|
||||
|
||||
matched, _ = regexp.MatchString("powershell -noninteractive -noprofile -executionpolicy bypass -file {{.Path}}", p.config.ElevatedExecuteCommand)
|
||||
if !matched {
|
||||
t.Errorf("expected default elevated execute command, but got : %s", p.config.ElevatedExecuteCommand)
|
||||
}
|
||||
|
||||
if p.config.ElevatedEnvVarFormat != `$env:%s="%s"; ` {
|
||||
t.Fatalf(`Default command should be powershell '$env:%%s="%%s"; ', but got %s`, p.config.ElevatedEnvVarFormat)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisionerPrepare_CustomExecuteCommands(t *testing.T) {
|
||||
var p Provisioner
|
||||
config := testConfig()
|
||||
config["execute_command"] = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
|
||||
config["elevated_execute_command"] = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
|
||||
|
||||
err := p.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
matched, _ := regexp.MatchString("c:/Windows/Temp/script-.*.ps1", p.config.RemotePath)
|
||||
if !matched {
|
||||
t.Errorf("unexpected remote path: %s", p.config.RemotePath)
|
||||
}
|
||||
|
||||
if p.config.ElevatedUser != "" {
|
||||
t.Error("expected elevated_user to be empty")
|
||||
}
|
||||
if p.config.ElevatedPassword != "" {
|
||||
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)
|
||||
}
|
||||
@ -476,7 +514,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 -noprofile -executionpolicy bypass -file c:/Windows/Temp/script.ps1'`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
@ -786,7 +824,7 @@ func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvision_createCommandText(t *testing.T) {
|
||||
func TestProvision_buildInterpolatedCommand(t *testing.T) {
|
||||
config := testConfig()
|
||||
config["remote_path"] = "c:/Windows/Temp/script.ps1"
|
||||
p := new(Provisioner)
|
||||
@ -800,9 +838,9 @@ func TestProvision_createCommandText(t *testing.T) {
|
||||
|
||||
// Non-elevated
|
||||
p.generatedData = make(map[string]interface{})
|
||||
cmd, _ := p.createCommandText()
|
||||
cmd, _ := p.buildInterpolatedCommand()
|
||||
|
||||
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 -noprofile -executionpolicy bypass -file c:/Windows/Temp/script.ps1`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
@ -811,7 +849,7 @@ func TestProvision_createCommandText(t *testing.T) {
|
||||
// Elevated
|
||||
p.config.ElevatedUser = "vagrant"
|
||||
p.config.ElevatedPassword = "vagrant"
|
||||
cmd, _ = p.createCommandText()
|
||||
cmd, _ = p.buildInterpolatedCommand()
|
||||
re = regexp.MustCompile(`powershell -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 {
|
||||
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"inline": "sc.exe start Life",
|
||||
"valid_exit_codes": ["1060"]
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
# Test fixture is a modified version of the example found at
|
||||
# https://www.powershellmagazine.com/2012/10/23/pstip-set-strictmode-why-should-you-care/
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$myNumbersCollection = 1..5
|
||||
if($myNumbersCollection -contains 3) {
|
||||
"collection contains 3"
|
||||
}
|
||||
else {
|
||||
"collection doesn't contain 3"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user