From 25c0b98363a8bbad9b14b1374af36bcf36477d6d Mon Sep 17 00:00:00 2001 From: Joel Vasallo Date: Thu, 18 Oct 2018 15:10:04 -0500 Subject: [PATCH] feat: ability to specify runtime OSs where shell-local should run --- common/shell-local/config.go | 3 + common/shell-local/run.go | 64 ++++++++++++------- .../docs/provisioners/shell-local.html.md | 8 +++ 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/common/shell-local/config.go b/common/shell-local/config.go index 56f9e05cd..bd895b547 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"` + // An array of multiple Runtime OSs to run on. + OnlyOn []string + // The file extension to use for the file generated from the inline commands TempfileExtension string `mapstructure:"tempfile_extension"` diff --git a/common/shell-local/run.go b/common/shell-local/run.go index c8f6160fc..505823833 100644 --- a/common/shell-local/run.go +++ b/common/shell-local/run.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "log" "os" + "runtime" "sort" "strings" @@ -58,31 +59,50 @@ func Run(ui packer.Ui, config *Config) (bool, error) { if err != nil { return false, err } - ui.Say(fmt.Sprintf("Running local shell script: %s", script)) - comm := &Communicator{ - ExecuteCommand: interpolatedCmds, + // Check if command can execute against runtime. + runCommand := false + if len(config.OnlyOn) > 0 { + for _, os := range config.OnlyOn { + if os == runtime.GOOS { + runCommand = true + } + } + } else { + runCommand = true } - // The remoteCmd generated here isn't actually run, but it allows us to - // use the same interafce for the shell-local communicator as we use for - // the other communicators; ultimately, this command is just used for - // buffers and for reading the final exit status. - flattenedCmd := strings.Join(interpolatedCmds, " ") - cmd := &packer.RemoteCmd{Command: flattenedCmd} - log.Printf("[INFO] (shell-local): starting local command: %s", flattenedCmd) - if err := cmd.StartWithUi(comm, ui); err != nil { - return false, fmt.Errorf( - "Error executing script: %s\n\n"+ - "Please see output above for more information.", - script) - } - if cmd.ExitStatus != 0 { - return false, fmt.Errorf( - "Erroneous exit code %d while executing script: %s\n\n"+ - "Please see output above for more information.", - cmd.ExitStatus, - script) + if runCommand { + ui.Say(fmt.Sprintf("Running local shell script: %s", script)) + + comm := &Communicator{ + ExecuteCommand: interpolatedCmds, + } + + // The remoteCmd generated here isn't actually run, but it allows us to + // use the same interafce for the shell-local communicator as we use for + // the other communicators; ultimately, this command is just used for + // buffers and for reading the final exit status. + flattenedCmd := strings.Join(interpolatedCmds, " ") + + cmd := &packer.RemoteCmd{Command: flattenedCmd} + log.Printf("[INFO] (shell-local): starting local command: %s", flattenedCmd) + if err := cmd.StartWithUi(comm, ui); err != nil { + return false, fmt.Errorf( + "Error executing script: %s\n\n"+ + "Please see output above for more information.", + script) + } + if cmd.ExitStatus != 0 { + return false, fmt.Errorf( + "Erroneous exit code %d while executing script: %s\n\n"+ + "Please see output above for more information.", + cmd.ExitStatus, + script) + } + } else { + ui.Say(fmt.Sprintf("Skipping local shell script due to runtime OS: %s", script)) + log.Printf("[INFO] (shell-local): skipping command due to runtime OS not specified.") } } diff --git a/website/source/docs/provisioners/shell-local.html.md b/website/source/docs/provisioners/shell-local.html.md index 5932ed69d..99724cb86 100644 --- a/website/source/docs/provisioners/shell-local.html.md +++ b/website/source/docs/provisioners/shell-local.html.md @@ -108,6 +108,14 @@ Optional parameters: **Important:** If you customize this, be sure to include something like the `-e` flag, otherwise individual steps failing won't fail the provisioner. +- `onlyon` (array of strings) - This is an array of + [runtime operating systems](https://golang.org/doc/install/source#environment) + where `shell-local` will only run on. This allows you to run `shell-local` *only* + on specific compatible operating systems. If specified, shell-local will only + execute if runtime operating system is in the list; otherwise it will skip the + `shell-local` command. The default behavior is for `shell-local` to run if + `onlyon` is not specified. + - `use_linux_pathing` (bool) - This is only relevant to windows hosts. If you are running Packer in a Windows environment with the Windows Subsystem for Linux feature enabled, and would like to invoke a bash script rather than