Revert "Merge pull request #5515 from DanHam/dot-source-env-vars"

revert so we can use a branch that's had more recent work done
This reverts commit e56849c605, reversing
changes made to 6d14eb6ea4.
This commit is contained in:
Megan Marsh 2018-02-02 09:58:39 -08:00
parent 79fe900378
commit addedbb680
3 changed files with 65 additions and 122 deletions

View File

@ -113,7 +113,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
}
if p.config.EnvVarFormat == "" {
p.config.EnvVarFormat = `$env:%s="%s"; `
p.config.EnvVarFormat = `$env:%s=\"%s\"; `
}
if p.config.ElevatedEnvVarFormat == "" {
@ -121,7 +121,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
}
if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}';exit $LastExitCode }"`
p.config.ExecuteCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"`
}
if p.config.ElevatedExecuteCommand == "" {
@ -331,19 +331,6 @@ func (p *Provisioner) retryable(f func() error) error {
}
}
// Enviroment variables required within the remote environment are uploaded within a PS script and
// then enabled by 'dot sourcing' the script immediately prior to execution of the main command
func (p *Provisioner) prepareEnvVars(elevated bool) (envVarPath string, err error) {
// Collate all required env vars into a plain string with required formatting applied
flattenedEnvVars := p.createFlattenedEnvVars(elevated)
// Create a powershell script on the target build fs containing the flattened env vars
envVarPath, err = p.uploadEnvVars(flattenedEnvVars)
if err != nil {
return "", err
}
return
}
func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) {
flattened = ""
envVars := make(map[string]string)
@ -380,19 +367,6 @@ func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) {
return
}
func (p *Provisioner) uploadEnvVars(flattenedEnvVars string) (envVarPath string, err error) {
// Upload all env vars to a powershell script on the target build file system
envVarReader := strings.NewReader(flattenedEnvVars)
uuid := uuid.TimeOrderedUUID()
envVarPath = fmt.Sprintf(`${env:SYSTEMROOT}\Temp\packer-env-vars-%s.ps1`, uuid)
log.Printf("Uploading env vars to %s", envVarPath)
err = p.communicator.Upload(envVarPath, envVarReader, nil)
if err != nil {
return "", fmt.Errorf("Error uploading ps script containing env vars: %s", err)
}
return
}
func (p *Provisioner) createCommandText() (command string, err error) {
// Return the interpolated command
if p.config.ElevatedUser == "" {
@ -403,15 +377,12 @@ func (p *Provisioner) createCommandText() (command string, err error) {
}
func (p *Provisioner) createCommandTextNonPrivileged() (command string, err error) {
// Prepare everything needed to enable the required env vars within the remote environment
envVarPath, err := p.prepareEnvVars(false)
if err != nil {
return "", err
}
// Create environment variables to set before executing the command
flattenedEnvVars := p.createFlattenedEnvVars(false)
p.config.ctx.Data = &ExecuteCommandTemplate{
Vars: flattenedEnvVars,
Path: p.config.RemotePath,
Vars: envVarPath,
}
command, err = interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
@ -424,10 +395,17 @@ func (p *Provisioner) createCommandTextNonPrivileged() (command string, err erro
}
func (p *Provisioner) createCommandTextPrivileged() (command string, err error) {
// Prepare everything needed to enable the required env vars within the remote environment
envVarPath, err := p.prepareEnvVars(false)
// Can't double escape the env vars, lets create shiny new ones
flattenedEnvVars := p.createFlattenedEnvVars(true)
// Need to create a mini ps1 script containing all of the environment variables we want;
// we'll be dot-sourcing this later
envVarReader := strings.NewReader(flattenedEnvVars)
uuid := uuid.TimeOrderedUUID()
envVarPath := fmt.Sprintf(`${env:SYSTEMROOT}\Temp\packer-env-vars-%s.ps1`, uuid)
log.Printf("Uploading env vars to %s", envVarPath)
err = p.communicator.Upload(envVarPath, envVarReader, nil)
if err != nil {
return "", err
return "", fmt.Errorf("Error preparing elevated powershell script: %s", err)
}
p.config.ctx.Data = &ExecuteCommandTemplate{

View File

@ -79,8 +79,8 @@ 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){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}';exit $LastExitCode }"` {
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}';exit $LastExitCode }"', but got '%s'`, p.config.ExecuteCommand)
if p.config.ExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"` {
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"', but got '%s'`, p.config.ExecuteCommand)
}
if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
@ -403,7 +403,7 @@ func TestProvisionerProvision_Inline(t *testing.T) {
ui := testUi()
p := new(Provisioner)
// Defaults provided by Packer - env vars should not appear in cmd
// Defaults provided by Packer
p.config.PackerBuildName = "vmware"
p.config.PackerBuilderType = "iso"
comm := new(packer.MockCommunicator)
@ -413,14 +413,11 @@ func TestProvisionerProvision_Inline(t *testing.T) {
t.Fatal("should not have error")
}
cmd := comm.StartCmd.Command
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){\$ProgressPreference='SilentlyContinue'};\. \${env:SYSTEMROOT}\\Temp\\packer-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/inlineScript.ps1';exit \$LastExitCode }"`)
matched := re.MatchString(cmd)
if !matched {
t.Fatalf("Got unexpected command: %s", cmd)
expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode }"`
if comm.StartCmd.Command != expectedCommand {
t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
}
// User supplied env vars should not change things
envVars := make([]string, 2)
envVars[0] = "FOO=BAR"
envVars[1] = "BAR=BAZ"
@ -433,11 +430,9 @@ func TestProvisionerProvision_Inline(t *testing.T) {
t.Fatal("should not have error")
}
cmd = comm.StartCmd.Command
re = regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){\$ProgressPreference='SilentlyContinue'};\. \${env:SYSTEMROOT}\\Temp\\packer-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/inlineScript.ps1';exit \$LastExitCode }"`)
matched = re.MatchString(cmd)
if !matched {
t.Fatalf("Got unexpected command: %s", cmd)
expectedCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR=\"BAZ\"; $env:FOO=\"BAR\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode }"`
if comm.StartCmd.Command != expectedCommand {
t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
}
}
@ -460,12 +455,11 @@ func TestProvisionerProvision_Scripts(t *testing.T) {
t.Fatal("should not have error")
}
cmd := comm.StartCmd.Command
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){\$ProgressPreference='SilentlyContinue'};\. \${env:SYSTEMROOT}\\Temp\\packer-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)
expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=\"footype\"; $env:PACKER_BUILD_NAME=\"foobuild\"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode }"`
if comm.StartCmd.Command != expectedCommand {
t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
}
}
func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
@ -494,11 +488,9 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
t.Fatal("should not have error")
}
cmd := comm.StartCmd.Command
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){\$ProgressPreference='SilentlyContinue'};\. \${env:SYSTEMROOT}\\Temp\\packer-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)
expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR=\"BAZ\"; $env:FOO=\"BAR\"; $env:PACKER_BUILDER_TYPE=\"footype\"; $env:PACKER_BUILD_NAME=\"foobuild\"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode }"`
if comm.StartCmd.Command != expectedCommand {
t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
}
}
@ -555,11 +547,11 @@ func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
{"FOO==bar"}, // User env var with value starting with equals
}
expected := []string{
`$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
`$env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
`$env:BAZ="qux"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
`$env:FOO="bar=baz"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
`$env:FOO="=bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
`$env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `,
`$env:FOO=\"bar\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `,
`$env:BAZ=\"qux\"; $env:FOO=\"bar\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `,
`$env:FOO=\"bar=baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `,
`$env:FOO=\"=bar\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `,
}
p := new(Provisioner)
@ -579,6 +571,7 @@ func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
}
func TestProvision_createCommandText(t *testing.T) {
config := testConfig()
config["remote_path"] = "c:/Windows/Temp/script.ps1"
p := new(Provisioner)
@ -593,46 +586,22 @@ func TestProvision_createCommandText(t *testing.T) {
// Non-elevated
cmd, _ := p.createCommandText()
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){\$ProgressPreference='SilentlyContinue'};\. \${env:SYSTEMROOT}\\Temp\\packer-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)
expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode }"`
if cmd != expectedCommand {
t.Fatalf("Expected Non-elevated command: %s, got %s", expectedCommand, cmd)
}
// Elevated
p.config.ElevatedUser = "vagrant"
p.config.ElevatedPassword = "vagrant"
cmd, _ = p.createCommandText()
re = regexp.MustCompile(`powershell -executionpolicy bypass -file "%TEMP%\\packer-elevated-shell-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1"`)
matched = re.MatchString(cmd)
matched, _ := regexp.MatchString("powershell -executionpolicy bypass -file \"%TEMP%(.{1})packer-elevated-shell.*", cmd)
if !matched {
t.Fatalf("Got unexpected elevated command: %s", cmd)
}
}
func TestProvision_uploadEnvVars(t *testing.T) {
p := new(Provisioner)
comm := new(packer.MockCommunicator)
p.communicator = comm
flattenedEnvVars := `$env:PACKER_BUILDER_TYPE="footype"; $env:PACKER_BUILD_NAME="foobuild";`
envVarPath, err := p.uploadEnvVars(flattenedEnvVars)
if err != nil {
t.Fatalf("Did not expect error: %s", err.Error())
}
if comm.UploadCalled != true {
t.Fatalf("Failed to upload env var file")
}
re := regexp.MustCompile(`\${env:SYSTEMROOT}\\Temp\\packer-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1`)
matched := re.MatchString(envVarPath)
if !matched {
t.Fatalf("Got unexpected path for env var file: %s", envVarPath)
}
}
func TestProvision_generateElevatedShellRunner(t *testing.T) {
// Non-elevated

View File

@ -1,8 +1,8 @@
---
description: |
The shell Packer provisioner provisions machines built by Packer using
shell scripts. Shell provisioning is the easiest way to get software
installed and configured on a machine.
The shell Packer provisioner provisions machines built by Packer using shell
scripts. Shell provisioning is the easiest way to get software installed and
configured on a machine.
layout: docs
page_title: 'PowerShell - Provisioners'
sidebar_current: 'docs-provisioners-powershell'
@ -29,21 +29,20 @@ The example below is fully functional.
## Configuration Reference
The reference of available configuration options is listed below. The only
required element is either "inline" or "script". Every other option is
optional.
required element is either "inline" or "script". Every other option is optional.
Exactly *one* of the following is required:
- `inline` (array of strings) - This is an array of commands to execute. The
commands are concatenated by newlines and turned into a single file, so
they are all executed within the same context. This allows you to change
commands are concatenated by newlines and turned into a single file, so they
are all executed within the same context. This allows you to change
directories in one command and use something in the directory in the next
and so on. Inline scripts are the easiest way to pull off simple tasks
within the machine.
- `script` (string) - The path to a script to upload and execute in
the machine. This path can be absolute or relative. If it is relative, it
is relative to the working directory when Packer is executed.
the machine. This path can be absolute or relative. If it is relative, it is
relative to the working directory when Packer is executed.
- `scripts` (array of strings) - An array of scripts to execute. The scripts
will be uploaded and executed in the order specified. Each script is
@ -52,12 +51,12 @@ Exactly *one* of the following is required:
Optional parameters:
- `binary` (boolean) - If true, specifies that the script(s) are binary
files, and Packer should therefore not convert Windows line endings to Unix
line endings (if there are any). By default this is false.
- `binary` (boolean) - If true, specifies that the script(s) are binary files,
and Packer should therefore not convert Windows line endings to Unix line
endings (if there are any). By default this is false.
- `elevated_execute_command` (string) - The command to use to execute the
elevated script. By default this is as follows:
- `elevated_execute_command` (string) - The command to use to execute the elevated
script. By default this is as follows:
``` powershell
powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"
@ -66,34 +65,32 @@ Optional parameters:
The value of this is treated as [configuration
template](/docs/templates/engine.html). There are two
available variables: `Path`, which is the path to the script to run, and
`Vars`, which is the location of a temp file containing the list of
`environment_vars`, if configured.
`Vars`, which is the location of a temp file containing the list of `environment_vars`, if configured.
- `environment_vars` (array of strings) - An array of key/value pairs to
inject prior to the execute\_command. The format should be `key=value`.
Packer injects some environmental variables by default into the
environment, as well, which are covered in the section below.
Packer injects some environmental variables by default into the environment,
as well, which are covered in the section below.
- `execute_command` (string) - The command to use to execute the script. By
default this is as follows:
``` powershell
powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"
powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"
```
The value of this is treated as [configuration
template](/docs/templates/engine.html). There are two
available variables: `Path`, which is the path to the script to run, and
`Vars`, which is the location of a temp file containing the list of
`environment_vars`, if configured.
`Vars`, which is the list of `environment_vars`, if configured.
- `elevated_user` and `elevated_password` (string) - If specified, the
PowerShell script will be run with elevated privileges using the given
Windows user.
- `remote_path` (string) - The path where the script will be uploaded to in
the machine. This defaults to "c:/Windows/Temp/script.ps1". This value must
be a writable location and any parent directories must already exist.
the machine. This defaults to "c:/Windows/Temp/script.ps1". This value must be a
writable location and any parent directories must already exist.
- `start_retry_timeout` (string) - The amount of time to attempt to *start*
the remote process. By default this is "5m" or 5 minutes. This setting
@ -114,10 +111,9 @@ commonly useful environmental variables:
This is most useful when Packer is making multiple builds and you want to
distinguish them slightly from a common provisioning script.
- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
the machine that the script is running on. This is useful if you want to
run only certain parts of the script on systems built with certain
builders.
- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create the
machine that the script is running on. This is useful if you want to run
only certain parts of the script on systems built with certain builders.
- `PACKER_HTTP_ADDR` If using a builder that provides an http server for file
transfer (such as hyperv, parallels, qemu, virtualbox, and vmware), this