diff --git a/common/shell-local/config.go b/common/shell-local/config.go index 6acda345a..e4c808de9 100644 --- a/common/shell-local/config.go +++ b/common/shell-local/config.go @@ -10,23 +10,24 @@ import ( "runtime" "strings" - "github.com/hashicorp/packer/common" + "github.com/hashicorp/packer/common/shell" configHelper "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/template/interpolate" ) type Config struct { - common.PackerConfig `mapstructure:",squash"` + shell.Provisioner `mapstructure:",squash"` // ** DEPRECATED: USE INLINE INSTEAD ** // ** Only Present for backwards compatibility ** // Command is the command to execute Command string - // An inline script to execute. Multiple strings are all executed - // in the context of a single shell. - Inline []string + // The command used to execute the script. The '{{ .Path }}' variable + // should be used to specify where the script goes, {{ .Vars }} + // can be used to inject the environment_vars into the environment. + ExecuteCommand []string `mapstructure:"execute_command"` // The shebang value used when running inline scripts. InlineShebang string `mapstructure:"inline_shebang"` @@ -37,24 +38,7 @@ type Config struct { // 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 - - // An array of multiple scripts to run. - Scripts []string - - // An array of environment variables that will be injected before - // your command(s) are executed. - Vars []string `mapstructure:"environment_vars"` - - EnvVarFormat string `mapstructure:"env_var_format"` // End dedupe with postprocessor - - // The command used to execute the script. The '{{ .Path }}' variable - // should be used to specify where the script goes, {{ .Vars }} - // can be used to inject the environment_vars into the environment. - ExecuteCommand []string `mapstructure:"execute_command"` - UseLinuxPathing bool `mapstructure:"use_linux_pathing"` ctx interpolate.Context diff --git a/common/shell-local/config.hcl2spec.go b/common/shell-local/config.hcl2spec.go index 353530f6b..257cd390d 100644 --- a/common/shell-local/config.hcl2spec.go +++ b/common/shell-local/config.hcl2spec.go @@ -16,16 +16,17 @@ type FlatConfig struct { PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` - Command *string `cty:"command"` Inline []string `cty:"inline"` + Script *string `cty:"script"` + Scripts []string `cty:"scripts"` + ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes"` + Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` + EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format"` + Command *string `cty:"command"` + ExecuteCommand []string `mapstructure:"execute_command" cty:"execute_command"` InlineShebang *string `mapstructure:"inline_shebang" cty:"inline_shebang"` OnlyOn []string `mapstructure:"only_on" cty:"only_on"` TempfileExtension *string `mapstructure:"tempfile_extension" cty:"tempfile_extension"` - Script *string `cty:"script"` - Scripts []string `cty:"scripts"` - Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` - EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format"` - ExecuteCommand []string `mapstructure:"execute_command" cty:"execute_command"` UseLinuxPathing *bool `mapstructure:"use_linux_pathing" cty:"use_linux_pathing"` } @@ -45,16 +46,17 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, "packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false}, "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "command": &hcldec.AttrSpec{Name: "command", Type: cty.String, Required: false}, "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false}, + "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false}, + "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false}, + "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false}, + "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false}, + "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false}, + "command": &hcldec.AttrSpec{Name: "command", Type: cty.String, Required: false}, + "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.List(cty.String), Required: false}, "inline_shebang": &hcldec.AttrSpec{Name: "inline_shebang", Type: cty.String, Required: false}, "only_on": &hcldec.AttrSpec{Name: "only_on", Type: cty.List(cty.String), Required: false}, "tempfile_extension": &hcldec.AttrSpec{Name: "tempfile_extension", Type: cty.String, Required: false}, - "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false}, - "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false}, - "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false}, - "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false}, - "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.List(cty.String), Required: false}, "use_linux_pathing": &hcldec.AttrSpec{Name: "use_linux_pathing", Type: cty.Bool, Required: false}, } return s diff --git a/common/shell-local/run.go b/common/shell-local/run.go index 39ac4bf97..06b8c78d3 100644 --- a/common/shell-local/run.go +++ b/common/shell-local/run.go @@ -97,12 +97,9 @@ func Run(ctx context.Context, ui packer.Ui, config *Config) (bool, error) { "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 err := config.ValidExitCode(cmd.ExitStatus()); err != nil { + return false, err } } diff --git a/common/shell/shell.go b/common/shell/shell.go index b698f4805..2484de74d 100644 --- a/common/shell/shell.go +++ b/common/shell/shell.go @@ -7,24 +7,10 @@ import "github.com/hashicorp/packer/common" type Provisioner struct { common.PackerConfig `mapstructure:",squash"` - // If true, the script contains binary and line endings will not be - // converted from Windows to Unix-style. - Binary bool - - // The command used to execute the script. The '{{ .Path }}' variable - // should be used to specify where the script goes, {{ .Vars }} - // can be used to inject the environment_vars into the environment. - ExecuteCommand string `mapstructure:"execute_command"` - // An inline script to execute. Multiple strings are all executed // in the context of a single shell. Inline []string - // The remote path where the local shell script will be uploaded to. - // This should be set to a writable file that is in a pre-existing directory. - // This defaults to remote_folder/remote_file - RemotePath string `mapstructure:"remote_path"` - // The local path of the shell script to upload and execute. Script string @@ -44,3 +30,19 @@ type Provisioner struct { // inside the `ExecuteCommand` template. EnvVarFormat string `mapstructure:"env_var_format"` } + +type ProvisionerRemoteSpecific struct { + // If true, the script contains binary and line endings will not be + // converted from Windows to Unix-style. + Binary bool + + // The remote path where the local shell script will be uploaded to. + // This should be set to a writable file that is in a pre-existing directory. + // This defaults to remote_folder/remote_file + RemotePath string `mapstructure:"remote_path"` + + // The command used to execute the script. The '{{ .Path }}' variable + // should be used to specify where the script goes, {{ .Vars }} + // can be used to inject the environment_vars into the environment. + ExecuteCommand string `mapstructure:"execute_command"` +} diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 69704233d..5ff6cbe93 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -40,6 +40,8 @@ var psEscape = strings.NewReplacer( type Config struct { shell.Provisioner `mapstructure:",squash"` + shell.ProvisionerRemoteSpecific `mapstructure:",squash"` + // The remote path where the file containing the environment variables // will be uploaded to. This should be set to a writable file that is in a // pre-existing directory. diff --git a/provisioner/powershell/provisioner.hcl2spec.go b/provisioner/powershell/provisioner.hcl2spec.go index 8350ebc8d..e1c543f62 100644 --- a/provisioner/powershell/provisioner.hcl2spec.go +++ b/provisioner/powershell/provisioner.hcl2spec.go @@ -16,15 +16,15 @@ type FlatConfig struct { PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` - Binary *bool `cty:"binary"` - ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` Inline []string `cty:"inline"` - RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` Script *string `cty:"script"` Scripts []string `cty:"scripts"` ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes"` Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format"` + Binary *bool `cty:"binary"` + RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` + ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` RemoteEnvVarPath *string `mapstructure:"remote_env_var_path" cty:"remote_env_var_path"` ElevatedExecuteCommand *string `mapstructure:"elevated_execute_command" cty:"elevated_execute_command"` StartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout"` @@ -50,15 +50,15 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, "packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false}, "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false}, - "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false}, - "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false}, "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false}, "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false}, "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false}, "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false}, "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false}, + "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false}, + "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false}, + "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, "remote_env_var_path": &hcldec.AttrSpec{Name: "remote_env_var_path", Type: cty.String, Required: false}, "elevated_execute_command": &hcldec.AttrSpec{Name: "elevated_execute_command", Type: cty.String, Required: false}, "start_retry_timeout": &hcldec.AttrSpec{Name: "start_retry_timeout", Type: cty.String, Required: false}, diff --git a/provisioner/shell/provisioner.go b/provisioner/shell/provisioner.go index 7c0bce800..824225aee 100644 --- a/provisioner/shell/provisioner.go +++ b/provisioner/shell/provisioner.go @@ -29,6 +29,8 @@ import ( type Config struct { shell.Provisioner `mapstructure:",squash"` + shell.ProvisionerRemoteSpecific `mapstructure:",squash"` + // The shebang value used when running inline scripts. InlineShebang string `mapstructure:"inline_shebang"` diff --git a/provisioner/shell/provisioner.hcl2spec.go b/provisioner/shell/provisioner.hcl2spec.go index 2b59e6436..9b48d3c3f 100644 --- a/provisioner/shell/provisioner.hcl2spec.go +++ b/provisioner/shell/provisioner.hcl2spec.go @@ -16,15 +16,15 @@ type FlatConfig struct { PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` - Binary *bool `cty:"binary"` - ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` Inline []string `cty:"inline"` - RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` Script *string `cty:"script"` Scripts []string `cty:"scripts"` ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes"` Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format"` + Binary *bool `cty:"binary"` + RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` + ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` InlineShebang *string `mapstructure:"inline_shebang" cty:"inline_shebang"` PauseAfter *string `mapstructure:"pause_after" cty:"pause_after"` UseEnvVarFile *bool `mapstructure:"use_env_var_file" cty:"use_env_var_file"` @@ -51,15 +51,15 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, "packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false}, "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false}, - "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false}, - "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false}, "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false}, "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false}, "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false}, "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false}, "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false}, + "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false}, + "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false}, + "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, "inline_shebang": &hcldec.AttrSpec{Name: "inline_shebang", Type: cty.String, Required: false}, "pause_after": &hcldec.AttrSpec{Name: "pause_after", Type: cty.String, Required: false}, "use_env_var_file": &hcldec.AttrSpec{Name: "use_env_var_file", Type: cty.Bool, Required: false}, diff --git a/provisioner/windows-shell/provisioner.go b/provisioner/windows-shell/provisioner.go index 8397c3491..2f42b145d 100644 --- a/provisioner/windows-shell/provisioner.go +++ b/provisioner/windows-shell/provisioner.go @@ -32,6 +32,8 @@ var retryableSleep = 2 * time.Second type Config struct { shell.Provisioner `mapstructure:",squash"` + shell.ProvisionerRemoteSpecific `mapstructure:",squash"` + // The timeout for retrying to start the process. Until this timeout // is reached, if the provisioner can't start a process, it retries. // This can be set high to allow for reboots. diff --git a/provisioner/windows-shell/provisioner.hcl2spec.go b/provisioner/windows-shell/provisioner.hcl2spec.go index 6bfd990d3..ee62b6bf2 100644 --- a/provisioner/windows-shell/provisioner.hcl2spec.go +++ b/provisioner/windows-shell/provisioner.hcl2spec.go @@ -16,15 +16,15 @@ type FlatConfig struct { PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` - Binary *bool `cty:"binary"` - ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` Inline []string `cty:"inline"` - RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` Script *string `cty:"script"` Scripts []string `cty:"scripts"` ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes"` Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format"` + Binary *bool `cty:"binary"` + RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` + ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` StartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout"` } @@ -44,15 +44,15 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, "packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false}, "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false}, - "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false}, - "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false}, "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false}, "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false}, "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false}, "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false}, "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false}, + "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false}, + "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false}, + "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, "start_retry_timeout": &hcldec.AttrSpec{Name: "start_retry_timeout", Type: cty.String, Required: false}, } return s diff --git a/website/source/docs/post-processors/shell-local.html.md b/website/source/docs/post-processors/shell-local.html.md index c24d00463..6989c0fd3 100644 --- a/website/source/docs/post-processors/shell-local.html.md +++ b/website/source/docs/post-processors/shell-local.html.md @@ -140,6 +140,9 @@ Optional parameters: the standard windows path to the script when providing a `script`. This is a beta feature. +- `valid_exit_codes` (list of ints) - Valid exit codes for the script. By + default this is just 0. + ## Execute Command To many new users, the `execute_command` is puzzling. However, it provides an diff --git a/website/source/docs/provisioners/shell-local.html.md.erb b/website/source/docs/provisioners/shell-local.html.md.erb index 8fd4ba210..66b478c98 100644 --- a/website/source/docs/provisioners/shell-local.html.md.erb +++ b/website/source/docs/provisioners/shell-local.html.md.erb @@ -133,6 +133,9 @@ Optional parameters: intend to use the shell-local provisioner to run a bash script, please ignore this option. +- `valid_exit_codes` (list of ints) - Valid exit codes for the script. By + default this is just 0. + <%= partial "partials/provisioners/common-config" %> ## Execute Command