From 1bea658e16cb5a45ea043b78276e81f2c4ec62db Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Wed, 4 Apr 2018 11:07:10 -0700 Subject: [PATCH] fix command and inline calls on windows --- common/shell-local/config.go | 19 +++- common/shell-local/run.go | 17 ++- .../docs/post-processors/shell-local.html.md | 102 ++++++++++++++++++ .../docs/provisioners/shell-local.html.md | 101 +++++++++++++++++ 4 files changed, 231 insertions(+), 8 deletions(-) diff --git a/common/shell-local/config.go b/common/shell-local/config.go index f4514a014..846e4b4a4 100644 --- a/common/shell-local/config.go +++ b/common/shell-local/config.go @@ -29,6 +29,9 @@ type Config struct { // The shebang value used when running inline scripts. InlineShebang string `mapstructure:"inline_shebang"` + // The file extension to use for the file generated from the inline commands + TempfileExtension string `mapstructure:"tempfile_extension"` + // The local path of the shell script to upload and execute. Script string @@ -39,7 +42,7 @@ type Config struct { // your command(s) are executed. Vars []string `mapstructure:"environment_vars"` - EnvVarFormat string + EnvVarFormat string `mapstructure:"env_var_format"` // End dedupe with postprocessor // The command used to execute the script. The '{{ .Path }}' variable @@ -76,8 +79,10 @@ func Validate(config *Config) error { if len(config.ExecuteCommand) == 0 { config.ExecuteCommand = []string{ "cmd", + "/V", "/C", "{{.Vars}}", + "call", "{{.Script}}", } } @@ -89,8 +94,7 @@ func Validate(config *Config) error { config.ExecuteCommand = []string{ "/bin/sh", "-c", - "{{.Vars}}", - "{{.Script}}", + "{{.Vars}} {{.Script}}", } } } @@ -168,12 +172,19 @@ func Validate(config *Config) error { // interact with. if config.EnvVarFormat == "" { if (runtime.GOOS == "windows") && !config.UseLinuxPathing { - config.EnvVarFormat = `set "%s=%s" && ` + config.EnvVarFormat = "set %s=%s && " } else { config.EnvVarFormat = "%s='%s' " } } + // drop unnecessary "." in extension; we add this later. + if config.TempfileExtension != "" { + if strings.HasPrefix(config.TempfileExtension, ".") { + config.TempfileExtension = config.TempfileExtension[1:] + } + } + // Do a check for bad environment variables, such as '=foo', 'foobar' for _, kv := range config.Vars { vs := strings.SplitN(kv, "=", 2) diff --git a/common/shell-local/run.go b/common/shell-local/run.go index 9e17d2d87..6af406522 100644 --- a/common/shell-local/run.go +++ b/common/shell-local/run.go @@ -30,8 +30,13 @@ func Run(ui packer.Ui, config *Config) (bool, error) { if err != nil { return false, err } - defer os.Remove(tempScriptFileName) scripts = append(scripts, tempScriptFileName) + + defer os.Remove(tempScriptFileName) + // figure out what extension the file should have, and rename it. + if config.TempfileExtension != "" { + os.Rename(tempScriptFileName, fmt.Sprintf("%s.%s", tempScriptFileName, config.TempfileExtension)) + } } // Create environment variables to set before executing the command @@ -78,14 +83,18 @@ func Run(ui packer.Ui, config *Config) (bool, error) { } func createInlineScriptFile(config *Config) (string, error) { - tf, err := ioutil.TempFile("", "packer-shell") + tf, err := ioutil.TempFile(os.TempDir(), "packer-shell") if err != nil { return "", fmt.Errorf("Error preparing shell script: %s", err) } - + defer tf.Close() // Write our contents to it writer := bufio.NewWriter(tf) - writer.WriteString(fmt.Sprintf("#!%s\n", config.InlineShebang)) + if config.InlineShebang != "" { + shebang := fmt.Sprintf("#!%s\n", config.InlineShebang) + log.Printf("Prepending inline script with %s", shebang) + writer.WriteString(shebang) + } for _, command := range config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return "", fmt.Errorf("Error preparing shell script: %s", err) diff --git a/website/source/docs/post-processors/shell-local.html.md b/website/source/docs/post-processors/shell-local.html.md index ab2f4bba3..3ace72792 100644 --- a/website/source/docs/post-processors/shell-local.html.md +++ b/website/source/docs/post-processors/shell-local.html.md @@ -227,3 +227,105 @@ are cleaned up. For a shell script, that means the script **must** exit with a zero code. You *must* be extra careful to `exit 0` when necessary. + + +## Usage Examples: + +Example of running a .cmd file on windows: + +``` + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest1"], + "scripts": ["./scripts/test_cmd.cmd"] + }, +``` + +Contents of "test_cmd.cmd": + +``` +echo %SHELLLOCALTEST% +``` + +Example of running an inline command on windows: +Required customization: tempfile_extension + +``` + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest2"], + "tempfile_extension": ".cmd", + "inline": ["echo %SHELLLOCALTEST%"] + }, +``` + +Example of running a bash command on windows using WSL: +Required customizations: use_linux_pathing and execute_command + +``` + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest3"], + "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"], + "use_linux_pathing": true, + "script": "./scripts/example_bash.sh" + } +``` + +Contents of "example_bash.sh": + +``` +#!/bin/bash +echo $SHELLLOCALTEST +``` + +Example of running a powershell script on windows: +Required customizations: env_var_format and execute_command + +``` + + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest4"], + "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"], + "env_var_format": "$env:%s=\"%s\"; ", + } +``` + +Example of running a powershell script on windows as "inline": +Required customizations: env_var_format, tempfile_extension, and execute_command + +``` + { + "type": "shell-local", + "tempfile_extension": ".ps1", + "environment_vars": ["SHELLLOCALTEST=ShellTest5"], + "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"], + "env_var_format": "$env:%s=\"%s\"; ", + "inline": ["write-output $env:SHELLLOCALTEST"] + } +``` + + +Example of running a bash script on linux: + +``` + { + "type": "shell-local", + "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"], + "scripts": ["./scripts/dummy_bash.sh"] + } +``` + +Example of running a bash "inline" on linux: + +``` + { + "type": "shell-local", + "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"], + "inline": ["echo hello", + "echo $PROVISIONERTEST"] + } +``` + + diff --git a/website/source/docs/provisioners/shell-local.html.md b/website/source/docs/provisioners/shell-local.html.md index eae9cf2ff..cadb1d6a1 100644 --- a/website/source/docs/provisioners/shell-local.html.md +++ b/website/source/docs/provisioners/shell-local.html.md @@ -197,3 +197,104 @@ are cleaned up. For a shell script, that means the script **must** exit with a zero code. You *must* be extra careful to `exit 0` when necessary. + + +## Usage Examples: + +Example of running a .cmd file on windows: + +``` + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest1"], + "scripts": ["./scripts/test_cmd.cmd"] + }, +``` + +Contents of "test_cmd.cmd": + +``` +echo %SHELLLOCALTEST% +``` + +Example of running an inline command on windows: +Required customization: tempfile_extension + +``` + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest2"], + "tempfile_extension": ".cmd", + "inline": ["echo %SHELLLOCALTEST%"] + }, +``` + +Example of running a bash command on windows using WSL: +Required customizations: use_linux_pathing and execute_command + +``` + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest3"], + "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"], + "use_linux_pathing": true, + "script": "./scripts/example_bash.sh" + } +``` + +Contents of "example_bash.sh": + +``` +#!/bin/bash +echo $SHELLLOCALTEST +``` + +Example of running a powershell script on windows: +Required customizations: env_var_format and execute_command + +``` + + { + "type": "shell-local", + "environment_vars": ["SHELLLOCALTEST=ShellTest4"], + "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"], + "env_var_format": "$env:%s=\"%s\"; ", + } +``` + +Example of running a powershell script on windows as "inline": +Required customizations: env_var_format, tempfile_extension, and execute_command + +``` + { + "type": "shell-local", + "tempfile_extension": ".ps1", + "environment_vars": ["SHELLLOCALTEST=ShellTest5"], + "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"], + "env_var_format": "$env:%s=\"%s\"; ", + "inline": ["write-output $env:SHELLLOCALTEST"] + } +``` + + +Example of running a bash script on linux: + +``` + { + "type": "shell-local", + "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"], + "scripts": ["./scripts/dummy_bash.sh"] + } +``` + +Example of running a bash "inline" on linux: + +``` + { + "type": "shell-local", + "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"], + "inline": ["echo hello", + "echo $PROVISIONERTEST"] + } +``` +