add new feature for telling shell-local whether to use linux pathing on windows; update docs with some examples.
This commit is contained in:
parent
e983a94a88
commit
51bcc7aa13
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -44,6 +45,8 @@ type Config struct {
|
||||||
// can be used to inject the environment_vars into the environment.
|
// can be used to inject the environment_vars into the environment.
|
||||||
ExecuteCommand []string `mapstructure:"execute_command"`
|
ExecuteCommand []string `mapstructure:"execute_command"`
|
||||||
|
|
||||||
|
UseLinuxPathing bool `mapstructure:"use_linux_pathing"`
|
||||||
|
|
||||||
Ctx interpolate.Context
|
Ctx interpolate.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,11 +70,6 @@ func Decode(config *Config, raws ...interface{}) error {
|
||||||
func Validate(config *Config) error {
|
func Validate(config *Config) error {
|
||||||
var errs *packer.MultiError
|
var errs *packer.MultiError
|
||||||
|
|
||||||
// Do not treat these defaults as a source of truth; the shell-local
|
|
||||||
// provisioner sets these defaults before Validate is called. Eventually
|
|
||||||
// we will have to bring the provisioner and post-processor defaults in
|
|
||||||
// line with one another, but for now the following may or may not be
|
|
||||||
// applied depending on where Validate is being called from.
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
if len(config.ExecuteCommand) == 0 {
|
if len(config.ExecuteCommand) == 0 {
|
||||||
config.ExecuteCommand = []string{
|
config.ExecuteCommand = []string{
|
||||||
|
@ -89,7 +87,8 @@ func Validate(config *Config) error {
|
||||||
config.ExecuteCommand = []string{
|
config.ExecuteCommand = []string{
|
||||||
"/bin/sh",
|
"/bin/sh",
|
||||||
"-c",
|
"-c",
|
||||||
"{{.Vars}} {{.Script}}",
|
"{{.Vars}}",
|
||||||
|
"{{.Script}}",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,6 +145,15 @@ func Validate(config *Config) error {
|
||||||
fmt.Errorf("Bad script '%s': %s", path, err))
|
fmt.Errorf("Bad script '%s': %s", path, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if config.UseLinuxPathing {
|
||||||
|
for index, script := range config.Scripts {
|
||||||
|
converted, err := convertToLinuxPath(script)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
config.Scripts[index] = converted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do a check for bad environment variables, such as '=foo', 'foobar'
|
// Do a check for bad environment variables, such as '=foo', 'foobar'
|
||||||
for _, kv := range config.Vars {
|
for _, kv := range config.Vars {
|
||||||
|
@ -162,3 +170,16 @@ func Validate(config *Config) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// C:/path/to/your/file becomes /mnt/c/path/to/your/file
|
||||||
|
func convertToLinuxPath(winPath string) (string, error) {
|
||||||
|
// get absolute path of script, and morph it into the bash path
|
||||||
|
winAbsPath, err := filepath.Abs(winPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error converting %s to absolute path: %s", winPath, err.Error())
|
||||||
|
}
|
||||||
|
winAbsPath = strings.Replace(winAbsPath, "\\", "/", -1)
|
||||||
|
splitPath := strings.SplitN(winAbsPath, ":/", 2)
|
||||||
|
winBashPath := fmt.Sprintf("/mnt/%s/%s", strings.ToLower(splitPath[0]), splitPath[1])
|
||||||
|
return winBashPath, nil
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -144,8 +145,17 @@ func createFlattenedEnvVars(config *Config) (flattened string) {
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
||||||
// Re-assemble vars surrounding value with single quotes and flatten
|
// Re-assemble vars surrounding value with single quotes and flatten
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
log.Printf("MEGAN NEED TO IMPLEMENT")
|
||||||
|
// createEnvVarsSourceFileWindows()
|
||||||
|
}
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
flattened += fmt.Sprintf("%s='%s' ", key, envVars[key])
|
flattened += fmt.Sprintf("%s='%s' ", key, envVars[key])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func createFlattenedEnvVarsWindows(
|
||||||
|
// // The default shell, cmd, can set vars via dot sourcing
|
||||||
|
// // set TESTXYZ=XYZ
|
||||||
|
// )
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
package shell
|
package shell
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
sl "github.com/hashicorp/packer/common/shell-local"
|
sl "github.com/hashicorp/packer/common/shell-local"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
)
|
)
|
||||||
|
@ -19,44 +14,15 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
convertPath := false
|
|
||||||
if len(p.config.ExecuteCommand) == 0 && runtime.GOOS == "windows" {
|
|
||||||
convertPath = true
|
|
||||||
p.config.ExecuteCommand = []string{
|
|
||||||
"bash",
|
|
||||||
"-c",
|
|
||||||
"{{.Vars}} {{.Script}}",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sl.Validate(&p.config)
|
err = sl.Validate(&p.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if convertPath {
|
|
||||||
for index, script := range p.config.Scripts {
|
|
||||||
p.config.Scripts[index], err = convertToWindowsBashPath(script)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertToWindowsBashPath(winPath string) (string, error) {
|
|
||||||
// get absolute path of script, and morph it into the bash path
|
|
||||||
winAbsPath, err := filepath.Abs(winPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("Error converting %s to absolute path: %s", winPath, err.Error())
|
|
||||||
}
|
|
||||||
winAbsPath = strings.Replace(winAbsPath, "\\", "/", -1)
|
|
||||||
winBashPath := strings.Replace(winAbsPath, "C:/", "/mnt/c/", 1)
|
|
||||||
return winBashPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provisioner) Provision(ui packer.Ui, _ packer.Communicator) error {
|
func (p *Provisioner) Provision(ui packer.Ui, _ packer.Communicator) error {
|
||||||
_, retErr := sl.Run(ui, &p.config)
|
_, retErr := sl.Run(ui, &p.config)
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
|
|
|
@ -60,7 +60,7 @@ Optional parameters:
|
||||||
as well, which are covered in the section below.
|
as well, which are covered in the section below.
|
||||||
|
|
||||||
- `execute_command` (array of strings) - The command used to execute the script. By
|
- `execute_command` (array of strings) - The command used to execute the script. By
|
||||||
default this is `["sh", "-c", "chmod +x \"{{.Script}}\"; {{.Vars}} \"{{.Script}}\""]`
|
default this is `["/bin/sh", "-c", "{{.Vars}}, "{{.Script}}"]`
|
||||||
on unix and `["cmd", "/c", "{{.Vars}}", "{{.Script}}"]` on windows.
|
on unix and `["cmd", "/c", "{{.Vars}}", "{{.Script}}"]` on windows.
|
||||||
This is treated as a [template engine](/docs/templates/engine.html).
|
This is treated as a [template engine](/docs/templates/engine.html).
|
||||||
There are two available variables: `Script`, which is the path to the script
|
There are two available variables: `Script`, which is the path to the script
|
||||||
|
@ -69,7 +69,9 @@ Optional parameters:
|
||||||
array is the shell program you want to use (for example, "sh" or
|
array is the shell program you want to use (for example, "sh" or
|
||||||
"/usr/local/bin/zsh" or even "powershell.exe" although anything other than
|
"/usr/local/bin/zsh" or even "powershell.exe" although anything other than
|
||||||
a flavor of the shell command language is not explicitly supported and may
|
a flavor of the shell command language is not explicitly supported and may
|
||||||
be broken by assumptions made within Packer).
|
be broken by assumptions made within Packer). It's worth noting that if you
|
||||||
|
choose to try to use shell-local for Powershell or other Windows commands,
|
||||||
|
the environment variables will not be set properly for your environment.
|
||||||
|
|
||||||
For backwards compatibility, `execute_command` will accept a string insetad
|
For backwards compatibility, `execute_command` will accept a string insetad
|
||||||
of an array of strings. If a single string or an array of strings with only
|
of an array of strings. If a single string or an array of strings with only
|
||||||
|
@ -89,13 +91,46 @@ Optional parameters:
|
||||||
**Important:** If you customize this, be sure to include something like the
|
**Important:** If you customize this, be sure to include something like the
|
||||||
`-e` flag, otherwise individual steps failing won't fail the provisioner.
|
`-e` flag, otherwise individual steps failing won't fail the provisioner.
|
||||||
|
|
||||||
## Execute Command Example
|
- `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
|
||||||
|
invoking a Cmd script, you'll need to set this flag to true; it tells Packer
|
||||||
|
to use the linux subsystem path for your script rather than the Windows path.
|
||||||
|
(e.g. /mnt/c/path/to/your/file instead of C:/path/to/your/file).
|
||||||
|
|
||||||
|
## Execute Command
|
||||||
|
|
||||||
To many new users, the `execute_command` is puzzling. However, it provides an
|
To many new users, the `execute_command` is puzzling. However, it provides an
|
||||||
important function: customization of how the command is executed. The most
|
important function: customization of how the command is executed. The most
|
||||||
common use case for this is dealing with **sudo password prompts**. You may also
|
common use case for this is dealing with **sudo password prompts**. You may also
|
||||||
need to customize this if you use a non-POSIX shell, such as `tcsh` on FreeBSD.
|
need to customize this if you use a non-POSIX shell, such as `tcsh` on FreeBSD.
|
||||||
|
|
||||||
|
### The Windows Linux Subsystem
|
||||||
|
|
||||||
|
If you have a bash script that you'd like to run on your Windows Linux
|
||||||
|
Subsystem as part of the shell-local post-processor, you must set
|
||||||
|
`execute_command` and `use_linux_pathing`.
|
||||||
|
|
||||||
|
The example below is a fully functional test config.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"builders": [
|
||||||
|
{
|
||||||
|
"type": "null",
|
||||||
|
"communicator": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"provisioners": [
|
||||||
|
{
|
||||||
|
"type": "shell-local",
|
||||||
|
"environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
|
||||||
|
"execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"]
|
||||||
|
"use_linux_pathing": true
|
||||||
|
"scripts": ["./scripts/.sh"]
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
## Default Environmental Variables
|
## Default Environmental Variables
|
||||||
|
|
||||||
In addition to being able to specify custom environmental variables using the
|
In addition to being able to specify custom environmental variables using the
|
||||||
|
|
Loading…
Reference in New Issue