Merge pull request #7678 from hashicorp/docker_windows_defaults

builder/docker: better windows defaults
This commit is contained in:
Megan Marsh 2019-05-24 11:19:32 -07:00 committed by GitHub
commit 1204213516
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 152 additions and 10 deletions

View File

@ -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 == "" {

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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