mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-09 00:32:09 -04:00
Merge pull request #13396 from hashicorp/karthik/powershell_fix
Powershell Script Config Environment Variables Fix
This commit is contained in:
commit
c3f3859d4a
4 changed files with 88 additions and 14 deletions
|
|
@ -11,6 +11,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -265,9 +266,43 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// extractScript prepares a temporary PowerShell script by prepending environment setup and debug config.
|
||||
// It copies the contents of the provided script file into the temp script and returns its path.
|
||||
func extractScript(p *Provisioner, script string) (string, error) {
|
||||
temp, err := tmp.File("powershell-provisioner-script")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer temp.Close()
|
||||
|
||||
baseString := `if (Test-Path variable:global:ProgressPreference)` +
|
||||
`{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};`
|
||||
|
||||
if p.config.DebugMode != 0 {
|
||||
baseString += fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode)
|
||||
}
|
||||
baseString += p.createFlattenedEnvVars(p.config.ElevatedUser != "")
|
||||
if _, err := temp.WriteString(baseString); err != nil {
|
||||
return "", fmt.Errorf("Error writing PowerShell script: %w", err)
|
||||
}
|
||||
|
||||
f, err := os.Open(script)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error opening powershell script: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := io.Copy(temp, f); err != nil {
|
||||
return "", fmt.Errorf("Error copying script contents: %w", err)
|
||||
}
|
||||
|
||||
return temp.Name(), nil
|
||||
|
||||
}
|
||||
|
||||
// Takes the inline scripts, adds a wrapper around 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) {
|
||||
func extractInlineScript(p *Provisioner) (string, error) {
|
||||
temp, err := tmp.File("powershell-provisioner")
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -280,7 +315,7 @@ func extractScript(p *Provisioner) (string, error) {
|
|||
// we concatenate all the inline commands
|
||||
for _, command := range p.config.Inline {
|
||||
log.Printf("Found command: %s", command)
|
||||
if _, err := commandBuilder.WriteString(command); err != nil {
|
||||
if _, err := commandBuilder.WriteString(command + "\n\t"); err != nil {
|
||||
return "", fmt.Errorf("failed to wrap script contents: %w", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -310,11 +345,12 @@ func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packe
|
|||
p.communicator = comm
|
||||
p.generatedData = generatedData
|
||||
|
||||
scripts := make([]string, len(p.config.Scripts))
|
||||
copy(scripts, p.config.Scripts)
|
||||
|
||||
var scripts []string
|
||||
// maps temp script paths to original script paths
|
||||
tempToOriginalScriptMap := make(map[string]string)
|
||||
if p.config.Inline != nil {
|
||||
temp, err := extractScript(p)
|
||||
temp, err := extractInlineScript(p)
|
||||
tempToOriginalScriptMap[temp] = temp
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
|
||||
}
|
||||
|
|
@ -323,12 +359,27 @@ func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packe
|
|||
defer os.Remove(temp)
|
||||
}
|
||||
|
||||
if len(p.config.Scripts) > 0 {
|
||||
|
||||
for _, script := range p.config.Scripts {
|
||||
temp, err := extractScript(p, script)
|
||||
tempToOriginalScriptMap[temp] = script
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Unable to extract script into a file: %s", err))
|
||||
}
|
||||
scripts = append(scripts, temp)
|
||||
// Defer removal until the function exits
|
||||
defer os.Remove(temp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// every provisioner run will only have one env var script file so lets add it first
|
||||
uploadedScripts := []string{p.config.RemoteEnvVarPath}
|
||||
for _, path := range scripts {
|
||||
ui.Say(fmt.Sprintf("Provisioning with powershell script: %s", path))
|
||||
ui.Say(fmt.Sprintf("Provisioning with powershell script: %s", tempToOriginalScriptMap[path]))
|
||||
|
||||
log.Printf("Opening %s for reading", path)
|
||||
log.Printf("Opening %s for reading", tempToOriginalScriptMap[path])
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error stating powershell script: %s", err)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
|
|
@ -82,6 +83,16 @@ func TestAccPowershellProvisioner_Inline(t *testing.T) {
|
|||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
out, err := os.ReadFile(logfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output := string(out)
|
||||
regexMatchString := "test_env_var: TestValue"
|
||||
if !regexp.MustCompile(regexp.QuoteMeta(regexMatchString)).MatchString(output) {
|
||||
t.Errorf("expected env string %q in logs:\n%s", regexMatchString, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
|
@ -105,6 +116,16 @@ func TestAccPowershellProvisioner_Script(t *testing.T) {
|
|||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
|
||||
out, err := os.ReadFile(logfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output := string(out)
|
||||
regexMatchString := "likewise, var2 is A`Backtick"
|
||||
if !regexp.MustCompile(regexp.QuoteMeta(regexMatchString)).MatchString(output) {
|
||||
t.Errorf("expected env string %q in logs:\n%s", regexMatchString, output)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ func TestProvisionerPrepare_extractScript(t *testing.T) {
|
|||
p := new(Provisioner)
|
||||
_ = p.Prepare(config)
|
||||
p.generatedData = generatedData()
|
||||
file, err := extractScript(p)
|
||||
file, err := extractInlineScript(p)
|
||||
defer os.Remove(file)
|
||||
if err != nil {
|
||||
t.Fatalf("Should not be error: %s", err)
|
||||
|
|
@ -36,7 +36,7 @@ func TestProvisionerPrepare_extractScript(t *testing.T) {
|
|||
|
||||
// File contents should contain 2 lines concatenated by newlines: foo\nbar
|
||||
readFile, err := os.ReadFile(file)
|
||||
expectedContents := "if (Test-Path variable:global:ProgressPreference) {\n set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'\n }\n \n $exitCode = 0\n try {\n $env:PACKER_BUILDER_TYPE=\"\"; $env:PACKER_BUILD_NAME=\"\"; \n foobar\n $exitCode = 0\n } catch {\n Write-Error \"An error occurred: $_\"\n $exitCode = 1\n }\n \n if ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {\n $exitCode = $LASTEXITCODE\n }\n \n Write-Host $result\n exit $exitCode"
|
||||
expectedContents := " \n\tif (Test-Path variable:global:ProgressPreference) {\n\t set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'\n\t}\n\t\n\t$exitCode = 0\n\ttry {\n\t$env:PACKER_BUILDER_TYPE=\"\"; $env:PACKER_BUILD_NAME=\"\"; \n\tfoo\n\tbar\n\t\n\t$exitCode = 0\n\t} catch {\n\tWrite-Error \"An error occurred: $_\"\n\t$exitCode = 1\n\t}\n\t\n\tif ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {\n\t\t$exitCode = $LASTEXITCODE\n\t}\n\t\n\tWrite-Host $result\n\texit $exitCode\n\n"
|
||||
normalizedExpectedContent := normalizeWhiteSpace(expectedContents)
|
||||
if err != nil {
|
||||
t.Fatalf("Should not be error: %s", err)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"type": "powershell",
|
||||
"environment_vars": "PackerRunUUID={{build `PackerRunUUID`}},ID={{build `ID`}}",
|
||||
"environment_vars": "PackerRunUUID={{build `PackerRunUUID`}},ID={{build `ID`}},TEST_ENV_VAR=TestValue",
|
||||
"inline": [
|
||||
"Write-Host \"$env:ID for provisioner.$env:PackerRunUUID\""
|
||||
"Write-Host \"$env:ID for provisioner.$env:PackerRunUUID build_name: $env:packer_build_name, test_env_var: $env:test_env_var\"",
|
||||
"setx BUILD_AMI_VERSION \"1.0.0\"",
|
||||
"setx BUILD_AMI_NAME custom_ami_name",
|
||||
"setx BUILD_AMI_DESCRIPTION \"This is a custom AMI created for testing purposes\""
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue