Merge pull request #7678 from hashicorp/docker_windows_defaults
builder/docker: better windows defaults
This commit is contained in:
commit
1204213516
|
@ -3,6 +3,7 @@ package docker
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
|
@ -124,7 +125,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
|||
}
|
||||
|
||||
if c.ContainerDir == "" {
|
||||
c.ContainerDir = "/packer-files"
|
||||
if runtime.GOOS == "windows" {
|
||||
c.ContainerDir = "c:/packer-files"
|
||||
} else {
|
||||
c.ContainerDir = "/packer-files"
|
||||
}
|
||||
}
|
||||
|
||||
if c.EcrLogin && c.LoginServer == "" {
|
||||
|
|
|
@ -23,6 +23,14 @@ type DecodeOpts struct {
|
|||
Interpolate bool
|
||||
InterpolateContext *interpolate.Context
|
||||
InterpolateFilter *interpolate.RenderFilter
|
||||
|
||||
DecodeHooks []mapstructure.DecodeHookFunc
|
||||
}
|
||||
|
||||
var DefaultDecodeHookFuncs = []mapstructure.DecodeHookFunc{
|
||||
uint8ToStringHook,
|
||||
mapstructure.StringToSliceHookFunc(","),
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
}
|
||||
|
||||
// Decode decodes the configuration into the target and optionally
|
||||
|
@ -60,17 +68,18 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
decodeHookFuncs := DefaultDecodeHookFuncs
|
||||
if len(config.DecodeHooks) != 0 {
|
||||
decodeHookFuncs = config.DecodeHooks
|
||||
}
|
||||
|
||||
// Build our decoder
|
||||
var md mapstructure.Metadata
|
||||
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
Result: target,
|
||||
Metadata: &md,
|
||||
WeaklyTypedInput: true,
|
||||
DecodeHook: mapstructure.ComposeDecodeHookFunc(
|
||||
uint8ToStringHook,
|
||||
mapstructure.StringToSliceHookFunc(","),
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
),
|
||||
DecodeHook: mapstructure.ComposeDecodeHookFunc(decodeHookFuncs...),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package powershell
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ExecutionPolicy setting to run the command(s).
|
||||
// For the powershell provider the default has historically been to bypass.
|
||||
type ExecutionPolicy int
|
||||
|
||||
const (
|
||||
ExecutionPolicyBypass ExecutionPolicy = iota
|
||||
ExecutionPolicyAllsigned
|
||||
ExecutionPolicyDefault
|
||||
ExecutionPolicyRemotesigned
|
||||
ExecutionPolicyRestricted
|
||||
ExecutionPolicyUndefined
|
||||
ExecutionPolicyUnrestricted
|
||||
ExecutionPolicyNone // not set
|
||||
)
|
||||
|
||||
func StringToExecutionPolicyHook(f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) {
|
||||
if f != reflect.String || t != reflect.Int {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
raw := data.(string)
|
||||
return ExecutionPolicyString(raw)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package powershell
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExecutionPolicy_Decode(t *testing.T) {
|
||||
config := map[string]interface{}{
|
||||
"inline": []interface{}{"foo", "bar"},
|
||||
"execution_policy": "allsigned",
|
||||
}
|
||||
p := new(Provisioner)
|
||||
err := p.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if p.config.ExecutionPolicy != ExecutionPolicyAllsigned {
|
||||
t.Fatalf("Expected AllSigned execution policy; got: %s", p.config.ExecutionPolicy)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Code generated by "enumer -transform snake -trimprefix ExecutionPolicy -type ExecutionPolicy provisioner/powershell/execution_policy.go"; DO NOT EDIT.
|
||||
|
||||
//
|
||||
package powershell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const _ExecutionPolicyName = "bypassallsigneddefaultremotesignedrestrictedundefinedunrestrictednone"
|
||||
|
||||
var _ExecutionPolicyIndex = [...]uint8{0, 6, 15, 22, 34, 44, 53, 65, 69}
|
||||
|
||||
func (i ExecutionPolicy) String() string {
|
||||
if i < 0 || i >= ExecutionPolicy(len(_ExecutionPolicyIndex)-1) {
|
||||
return fmt.Sprintf("ExecutionPolicy(%d)", i)
|
||||
}
|
||||
return _ExecutionPolicyName[_ExecutionPolicyIndex[i]:_ExecutionPolicyIndex[i+1]]
|
||||
}
|
||||
|
||||
var _ExecutionPolicyValues = []ExecutionPolicy{0, 1, 2, 3, 4, 5, 6, 7}
|
||||
|
||||
var _ExecutionPolicyNameToValueMap = map[string]ExecutionPolicy{
|
||||
_ExecutionPolicyName[0:6]: 0,
|
||||
_ExecutionPolicyName[6:15]: 1,
|
||||
_ExecutionPolicyName[15:22]: 2,
|
||||
_ExecutionPolicyName[22:34]: 3,
|
||||
_ExecutionPolicyName[34:44]: 4,
|
||||
_ExecutionPolicyName[44:53]: 5,
|
||||
_ExecutionPolicyName[53:65]: 6,
|
||||
_ExecutionPolicyName[65:69]: 7,
|
||||
}
|
||||
|
||||
// ExecutionPolicyString retrieves an enum value from the enum constants string name.
|
||||
// Throws an error if the param is not part of the enum.
|
||||
func ExecutionPolicyString(s string) (ExecutionPolicy, error) {
|
||||
if val, ok := _ExecutionPolicyNameToValueMap[s]; ok {
|
||||
return val, nil
|
||||
}
|
||||
return 0, fmt.Errorf("%s does not belong to ExecutionPolicy values", s)
|
||||
}
|
||||
|
||||
// ExecutionPolicyValues returns all values of the enum
|
||||
func ExecutionPolicyValues() []ExecutionPolicy {
|
||||
return _ExecutionPolicyValues
|
||||
}
|
||||
|
||||
// IsAExecutionPolicy returns "true" if the value is listed in the enum definition. "false" otherwise
|
||||
func (i ExecutionPolicy) IsAExecutionPolicy() bool {
|
||||
for _, v := range _ExecutionPolicyValues {
|
||||
if i == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -66,6 +66,8 @@ type Config struct {
|
|||
ElevatedUser string `mapstructure:"elevated_user"`
|
||||
ElevatedPassword string `mapstructure:"elevated_password"`
|
||||
|
||||
ExecutionPolicy ExecutionPolicy `mapstructure:"execution_policy"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
|
@ -84,6 +86,17 @@ type EnvVarsTemplate struct {
|
|||
WinRMPassword string
|
||||
}
|
||||
|
||||
func (p *Provisioner) defaultExecuteCommand() string {
|
||||
baseCmd := `& { if (Test-Path variable:global:ProgressPreference)` +
|
||||
`{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};` +
|
||||
`. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }`
|
||||
if p.config.ExecutionPolicy == ExecutionPolicyNone {
|
||||
return baseCmd
|
||||
} else {
|
||||
return fmt.Sprintf(`powershell -executionpolicy %s "%s"`, p.config.ExecutionPolicy, baseCmd)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// Create passthrough for winrm password so we can fill it in once we know
|
||||
// it
|
||||
|
@ -100,6 +113,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
|||
"elevated_execute_command",
|
||||
},
|
||||
},
|
||||
DecodeHooks: append(config.DefaultDecodeHookFuncs, StringToExecutionPolicyHook),
|
||||
}, raws...)
|
||||
|
||||
if err != nil {
|
||||
|
@ -115,11 +129,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
|||
}
|
||||
|
||||
if p.config.ExecuteCommand == "" {
|
||||
p.config.ExecuteCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
|
||||
p.config.ExecuteCommand = p.defaultExecuteCommand()
|
||||
}
|
||||
|
||||
if p.config.ElevatedExecuteCommand == "" {
|
||||
p.config.ElevatedExecuteCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
|
||||
p.config.ElevatedExecuteCommand = p.defaultExecuteCommand()
|
||||
}
|
||||
|
||||
if p.config.Inline != nil && len(p.config.Inline) == 0 {
|
||||
|
@ -272,6 +286,8 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C
|
|||
// Close the original file since we copied it
|
||||
f.Close()
|
||||
|
||||
log.Printf("%s returned with exit code %d", p.config.RemotePath, cmd.ExitStatus())
|
||||
|
||||
if err := p.config.ValidExitCode(cmd.ExitStatus()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -232,8 +232,8 @@ You must specify (only) one of `commit`, `discard`, or `export_path`.
|
|||
|
||||
- `container_dir` (string) - The directory inside container to mount temp
|
||||
directory from host server for work [file
|
||||
provisioner](/docs/provisioners/file.html). By default this is set to
|
||||
`/packer-files`.
|
||||
provisioner](/docs/provisioners/file.html). This defaults to
|
||||
`c:/packer-files` on windows and `/packer-files` on other systems.
|
||||
|
||||
- `fix_upload_owner` (boolean) - If true, files uploaded to the container
|
||||
will be owned by the user the container is running as. If false, the owner
|
||||
|
|
|
@ -102,6 +102,12 @@ The example below is fully functional.
|
|||
"elevated_password": "",
|
||||
```
|
||||
|
||||
- `execution_policy` - To run ps scripts on windows packer defaults this to
|
||||
"bypass" and wraps the command to run. Setting this to "none" will prevent
|
||||
wrapping, allowing to see exit codes on docker for windows. Possible values
|
||||
are "bypass", "allsigned", "default", "remotesigned", "restricted",
|
||||
"undefined", "unrestricted", "none".
|
||||
|
||||
- `remote_path` (string) - The path where the PowerShell script will be
|
||||
uploaded to within the target build machine. This defaults to
|
||||
`C:/Windows/Temp/script-UUID.ps1` where UUID is replaced with a dynamically
|
||||
|
|
Loading…
Reference in New Issue