Merge pull request #6579 from hashicorp/reinterpolate_winrm_step
use statebag instead of SetSharedState for winRM password
This commit is contained in:
commit
d356817890
|
@ -12,7 +12,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
@ -95,15 +94,13 @@ WaitLoop:
|
|||
"Password (since debug is enabled): %s", s.Comm.WinRMPassword))
|
||||
}
|
||||
// store so that we can access this later during provisioning
|
||||
|
||||
commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName)
|
||||
state.Put("winrm_password", s.Comm.WinRMPassword)
|
||||
packer.LogSecretFilter.Set(s.Comm.WinRMPassword)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepGetPassword) Cleanup(multistep.StateBag) {
|
||||
commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName)
|
||||
}
|
||||
|
||||
func (s *StepGetPassword) waitForPassword(state multistep.StateBag, cancel <-chan struct{}) (string, error) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
"github.com/hashicorp/packer/builder/azure/common/constants"
|
||||
"github.com/hashicorp/packer/builder/azure/pkcs12"
|
||||
"github.com/hashicorp/packer/common"
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
@ -361,10 +360,7 @@ func setRuntimeValues(c *Config) {
|
|||
var tempName = NewTempName()
|
||||
|
||||
c.tmpAdminPassword = tempName.AdminPassword
|
||||
// store so that we can access this later during provisioning
|
||||
commonhelper.SetSharedState("winrm_password", c.tmpAdminPassword, c.PackerConfig.PackerBuildName)
|
||||
packer.LogSecretFilter.Set(c.tmpAdminPassword)
|
||||
|
||||
c.tmpCertificatePassword = tempName.CertificatePassword
|
||||
if c.TempComputeName == "" {
|
||||
c.tmpComputeName = tempName.ComputeName
|
||||
|
|
|
@ -3,7 +3,6 @@ package arm
|
|||
import (
|
||||
"context"
|
||||
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
@ -15,11 +14,10 @@ type StepSaveWinRMPassword struct {
|
|||
|
||||
func (s *StepSaveWinRMPassword) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
// store so that we can access this later during provisioning
|
||||
commonhelper.SetSharedState("winrm_password", s.Password, s.BuildName)
|
||||
state.Put("winrm_password", s.Password)
|
||||
packer.LogSecretFilter.Set(s.Password)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepSaveWinRMPassword) Cleanup(multistep.StateBag) {
|
||||
commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
@ -114,7 +113,6 @@ func (s *StepCreateWindowsPassword) Run(_ context.Context, state multistep.State
|
|||
}
|
||||
|
||||
state.Put("winrm_password", data.password)
|
||||
commonhelper.SetSharedState("winrm_password", data.password, c.PackerConfig.PackerBuildName)
|
||||
packer.LogSecretFilter.Set(data.password)
|
||||
|
||||
return multistep.ActionContinue
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
@ -52,8 +51,9 @@ func (s *stepGetDefaultCredentials) Run(ctx context.Context, state multistep.Sta
|
|||
}
|
||||
|
||||
// store so that we can access this later during provisioning
|
||||
commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName)
|
||||
state.Put("winrm_password", s.Comm.WinRMPassword)
|
||||
packer.LogSecretFilter.Set(s.Comm.WinRMPassword)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ type Config struct {
|
|||
UseLinuxPathing bool `mapstructure:"use_linux_pathing"`
|
||||
|
||||
Ctx interpolate.Context
|
||||
|
||||
// internal use only; for the provisioner.
|
||||
WinRMPassword string
|
||||
}
|
||||
|
||||
func Decode(config *Config, raws ...interface{}) error {
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
@ -70,6 +69,7 @@ func Run(ui packer.Ui, config *Config) (bool, error) {
|
|||
// buffers and for reading the final exit status.
|
||||
flattenedCmd := strings.Join(interpolatedCmds, " ")
|
||||
cmd := &packer.RemoteCmd{Command: flattenedCmd}
|
||||
packer.LogSecretFilter.Set(config.WinRMPassword)
|
||||
log.Printf("[INFO] (shell-local): starting local command: %s", flattenedCmd)
|
||||
if err := cmd.StartWithUi(comm, ui); err != nil {
|
||||
return false, fmt.Errorf(
|
||||
|
@ -105,7 +105,7 @@ func createInlineScriptFile(config *Config) (string, error) {
|
|||
|
||||
// generate context so you can interpolate the command
|
||||
config.Ctx.Data = &EnvVarsTemplate{
|
||||
WinRMPassword: getWinRMPassword(config.PackerBuildName),
|
||||
WinRMPassword: config.WinRMPassword,
|
||||
}
|
||||
|
||||
for _, command := range config.Inline {
|
||||
|
@ -139,7 +139,7 @@ func createInterpolatedCommands(config *Config, script string, flattenedEnvVars
|
|||
Vars: flattenedEnvVars,
|
||||
Script: script,
|
||||
Command: script,
|
||||
WinRMPassword: getWinRMPassword(config.PackerBuildName),
|
||||
WinRMPassword: config.WinRMPassword,
|
||||
}
|
||||
|
||||
interpolatedCmds := make([]string, len(config.ExecuteCommand))
|
||||
|
@ -169,7 +169,7 @@ func createFlattenedEnvVars(config *Config) (string, error) {
|
|||
|
||||
// interpolate environment variables
|
||||
config.Ctx.Data = &EnvVarsTemplate{
|
||||
WinRMPassword: getWinRMPassword(config.PackerBuildName),
|
||||
WinRMPassword: config.WinRMPassword,
|
||||
}
|
||||
// Split vars into key/value components
|
||||
for _, envVar := range config.Vars {
|
||||
|
@ -196,9 +196,3 @@ func createFlattenedEnvVars(config *Config) (string, error) {
|
|||
}
|
||||
return flattened, nil
|
||||
}
|
||||
|
||||
func getWinRMPassword(buildName string) string {
|
||||
winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName)
|
||||
packer.LogSecretFilter.Set(winRMPass)
|
||||
return winRMPass
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ type StepProvision struct {
|
|||
Comm packer.Communicator
|
||||
}
|
||||
|
||||
type ProvisionHookData struct {
|
||||
WinRMPassword string
|
||||
}
|
||||
|
||||
func (s *StepProvision) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
comm := s.Comm
|
||||
if comm == nil {
|
||||
|
@ -33,12 +37,21 @@ func (s *StepProvision) Run(_ context.Context, state multistep.StateBag) multist
|
|||
hook := state.Get("hook").(packer.Hook)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
// Save data we need to give to provisioners
|
||||
WinRMPassword, ok := state.GetOk("winrm_password")
|
||||
if !ok {
|
||||
WinRMPassword = ""
|
||||
} else {
|
||||
WinRMPassword = WinRMPassword.(string)
|
||||
}
|
||||
phd := ProvisionHookData{WinRMPassword.(string)}
|
||||
|
||||
// Run the provisioner in a goroutine so we can continually check
|
||||
// for cancellations...
|
||||
log.Println("Running the provision hook")
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
errCh <- hook.Run(packer.HookProvision, ui, comm, nil)
|
||||
errCh <- hook.Run(packer.HookProvision, ui, comm, phd)
|
||||
}()
|
||||
|
||||
for {
|
||||
|
|
|
@ -44,6 +44,10 @@ type ProvisionHook struct {
|
|||
runningProvisioner Provisioner
|
||||
}
|
||||
|
||||
type ProvisionHookData struct {
|
||||
WinRMPassword string
|
||||
}
|
||||
|
||||
// Runs the provisioners in order.
|
||||
func (h *ProvisionHook) Run(name string, ui Ui, comm Communicator, data interface{}) error {
|
||||
// Shortcut
|
||||
|
@ -71,8 +75,15 @@ func (h *ProvisionHook) Run(name string, ui Ui, comm Communicator, data interfac
|
|||
h.lock.Unlock()
|
||||
|
||||
ts := CheckpointReporter.AddSpan(p.TypeName, "provisioner", p.Config)
|
||||
// re-run prepare with builder-generated config variables (e.g. WinRMPassword)
|
||||
// Hack Alert. #SorryNotSorry.
|
||||
err := p.Provisioner.Prepare(data)
|
||||
if err != nil {
|
||||
log.Printf("Error performing secondary Prepare: %s", err)
|
||||
}
|
||||
|
||||
err := p.Provisioner.Provision(ui, comm)
|
||||
// Finally, provision.
|
||||
err = p.Provisioner.Provision(ui, comm)
|
||||
|
||||
ts.End(err)
|
||||
if err != nil {
|
||||
|
|
|
@ -14,8 +14,10 @@ type MockProvisioner struct {
|
|||
}
|
||||
|
||||
func (t *MockProvisioner) Prepare(configs ...interface{}) error {
|
||||
t.PrepCalled = true
|
||||
t.PrepConfigs = configs
|
||||
if !t.PrepCalled {
|
||||
t.PrepCalled = true
|
||||
t.PrepConfigs = configs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
|
@ -58,6 +57,8 @@ type Config struct {
|
|||
UseSFTP bool `mapstructure:"use_sftp"`
|
||||
InventoryDirectory string `mapstructure:"inventory_directory"`
|
||||
InventoryFile string `mapstructure:"inventory_file"`
|
||||
// for internal use only; unsettable by user.
|
||||
winrmpassword string
|
||||
}
|
||||
|
||||
type Provisioner struct {
|
||||
|
@ -73,14 +74,35 @@ type PassthroughTemplate struct {
|
|||
}
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// This is a bit of a hack. For provisioners that need access to
|
||||
// auto-generated WinRMPasswords, the mechanism of keeping provisioner data
|
||||
// and build data totally segregated breaks down. We get around this by
|
||||
// having the builder stash the WinRMPassword in the state bag, then
|
||||
// grabbing it out of the statebag inside of StepProvision. Then, when
|
||||
// the time comes to provision for real, we run the prepare step one more
|
||||
// time, now with WinRMPassword defined in the raws, and can store the
|
||||
// password on the provisioner config without overwriting the rest of the
|
||||
// work we've already done in the first prepare run.
|
||||
if len(raws) == 1 {
|
||||
for k, v := range raws[0].(map[interface{}]interface{}) {
|
||||
if k.(string) == "WinRMPassword" {
|
||||
p.config.winrmpassword = v.(string)
|
||||
|
||||
// Even if WinRMPassword is not gonna be used, we've stored the
|
||||
// key and pointed it to an empty string. That means we'll
|
||||
// always reach this on our second-run of Prepare()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.done = make(chan struct{})
|
||||
|
||||
// Create passthrough for winrm password so we can fill it in once we know
|
||||
// it
|
||||
// don't interpolate winrmpassword yet; if we've made it to this line, then
|
||||
// we have not obtained the winrm password yet.
|
||||
p.config.ctx.Data = &PassthroughTemplate{
|
||||
WinRMPassword: `{{.WinRMPassword}}`,
|
||||
}
|
||||
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
|
@ -200,8 +222,9 @@ func (p *Provisioner) getVersion() error {
|
|||
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
||||
ui.Say("Provisioning with Ansible...")
|
||||
// Interpolate env vars to check for .WinRMPassword
|
||||
packer.LogSecretFilter.Set(p.config.winrmpassword)
|
||||
p.config.ctx.Data = &PassthroughTemplate{
|
||||
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
|
||||
WinRMPassword: p.config.winrmpassword,
|
||||
}
|
||||
for i, envVar := range p.config.AnsibleEnvVars {
|
||||
envVar, err := interpolate.Render(envVar, &p.config.ctx)
|
||||
|
@ -420,12 +443,7 @@ func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator, pri
|
|||
|
||||
// remove winrm password from command, if it's been added
|
||||
flattenedCmd := strings.Join(cmd.Args, " ")
|
||||
sanitized := flattenedCmd
|
||||
if len(getWinRMPassword(p.config.PackerBuildName)) > 0 {
|
||||
sanitized = strings.Replace(sanitized,
|
||||
getWinRMPassword(p.config.PackerBuildName), "*****", -1)
|
||||
}
|
||||
ui.Say(fmt.Sprintf("Executing Ansible: %s", sanitized))
|
||||
ui.Say(fmt.Sprintf("Executing Ansible: %s", flattenedCmd))
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
|
@ -553,12 +571,6 @@ func newSigner(privKeyFile string) (*signer, error) {
|
|||
return signer, nil
|
||||
}
|
||||
|
||||
func getWinRMPassword(buildName string) string {
|
||||
winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName)
|
||||
packer.LogSecretFilter.Set(winRMPass)
|
||||
return winRMPass
|
||||
}
|
||||
|
||||
// Ui provides concurrency-safe access to packer.Ui.
|
||||
type Ui struct {
|
||||
sem chan int
|
||||
|
|
|
@ -16,8 +16,8 @@ import (
|
|||
|
||||
// Be sure to remove the Ansible stub file in each test with:
|
||||
// defer os.Remove(config["command"].(string))
|
||||
func testConfig(t *testing.T) map[string]interface{} {
|
||||
m := make(map[string]interface{})
|
||||
func testConfig(t *testing.T) map[interface{}]interface{} {
|
||||
m := make((map[interface{}]interface{}))
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
commonhelper "github.com/hashicorp/packer/helper/common"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
|
@ -98,6 +97,9 @@ type Config struct {
|
|||
// Changes will not be effective until the system is rebooted."
|
||||
ValidExitCodes []int `mapstructure:"valid_exit_codes"`
|
||||
|
||||
// internal variable, to be written to at provisioner run time.
|
||||
winrmpassword string
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
|
@ -117,8 +119,28 @@ type EnvVarsTemplate struct {
|
|||
}
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// Create passthrough for winrm password so we can fill it in once we know
|
||||
// it
|
||||
// This is a bit of a hack. For provisioners that need access to
|
||||
// auto-generated WinRMPasswords, the mechanism of keeping provisioner data
|
||||
// and build data totally segregated breaks down. We get around this by
|
||||
// having the builder stash the WinRMPassword in the state bag, then
|
||||
// grabbing it out of the statebag inside of StepProvision. Then, when
|
||||
// the time comes to provision for real, we run the prepare step one more
|
||||
// time, now with WinRMPassword defined in the raws, and can store the
|
||||
// password on the provisioner config without overwriting the rest of the
|
||||
// work we've already done in the first prepare run.
|
||||
if len(raws) == 1 {
|
||||
for k, v := range raws[0].(map[interface{}]interface{}) {
|
||||
if k.(string) == "WinRMPassword" {
|
||||
p.config.winrmpassword = v.(string)
|
||||
// Even if WinRMPassword is not gonna be used, we've stored the
|
||||
// key and pointed it to an empty string. That means we'll
|
||||
// always reach this on our second-run of Prepare()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only get here if it's the first time the Provisioner's Prepare is run
|
||||
p.config.ctx.Data = &EnvVarsTemplate{
|
||||
WinRMPassword: `{{.WinRMPassword}}`,
|
||||
}
|
||||
|
@ -135,7 +157,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
|||
}, raws...)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("Error decoding powershell provisioner template: %s", err)
|
||||
}
|
||||
|
||||
if p.config.EnvVarFormat == "" {
|
||||
|
@ -261,7 +283,7 @@ func extractScript(p *Provisioner) (string, error) {
|
|||
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
||||
ui.Say(fmt.Sprintf("Provisioning with Powershell..."))
|
||||
p.communicator = comm
|
||||
|
||||
packer.LogSecretFilter.Set(p.config.winrmpassword)
|
||||
scripts := make([]string, len(p.config.Scripts))
|
||||
copy(scripts, p.config.Scripts)
|
||||
|
||||
|
@ -392,7 +414,7 @@ func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) {
|
|||
|
||||
// interpolate environment variables
|
||||
p.config.ctx.Data = &EnvVarsTemplate{
|
||||
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
|
||||
WinRMPassword: p.config.winrmpassword,
|
||||
}
|
||||
// Split vars into key/value components
|
||||
for _, envVar := range p.config.Vars {
|
||||
|
@ -467,7 +489,7 @@ func (p *Provisioner) createCommandTextNonPrivileged() (command string, err erro
|
|||
p.config.ctx.Data = &ExecuteCommandTemplate{
|
||||
Path: p.config.RemotePath,
|
||||
Vars: p.config.RemoteEnvVarPath,
|
||||
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
|
||||
WinRMPassword: p.config.winrmpassword,
|
||||
}
|
||||
command, err = interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
|
||||
|
@ -479,12 +501,6 @@ func (p *Provisioner) createCommandTextNonPrivileged() (command string, err erro
|
|||
return command, nil
|
||||
}
|
||||
|
||||
func getWinRMPassword(buildName string) string {
|
||||
winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName)
|
||||
packer.LogSecretFilter.Set(winRMPass)
|
||||
return winRMPass
|
||||
}
|
||||
|
||||
func (p *Provisioner) createCommandTextPrivileged() (command string, err error) {
|
||||
// Prepare everything needed to enable the required env vars within the
|
||||
// remote environment
|
||||
|
@ -496,7 +512,7 @@ func (p *Provisioner) createCommandTextPrivileged() (command string, err error)
|
|||
p.config.ctx.Data = &ExecuteCommandTemplate{
|
||||
Path: p.config.RemotePath,
|
||||
Vars: p.config.RemoteEnvVarPath,
|
||||
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
|
||||
WinRMPassword: p.config.winrmpassword,
|
||||
}
|
||||
command, err = interpolate.Render(p.config.ElevatedExecuteCommand, &p.config.ctx)
|
||||
if err != nil {
|
||||
|
@ -555,7 +571,7 @@ func (p *Provisioner) generateElevatedRunner(command string) (uploadedPath strin
|
|||
}
|
||||
// Replace ElevatedPassword for winrm users who used this feature
|
||||
p.config.ctx.Data = &EnvVarsTemplate{
|
||||
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
|
||||
WinRMPassword: p.config.winrmpassword,
|
||||
}
|
||||
|
||||
p.config.ElevatedPassword, _ = interpolate.Render(p.config.ElevatedPassword, &p.config.ctx)
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
func testConfig() map[interface{}]interface{} {
|
||||
return map[interface{}]interface{}{
|
||||
"inline": []interface{}{"foo", "bar"},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,27 @@ type Provisioner struct {
|
|||
}
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// This is a bit of a hack. For provisioners that need access to
|
||||
// auto-generated WinRMPasswords, the mechanism of keeping provisioner data
|
||||
// and build data totally segregated breaks down. We get around this by
|
||||
// having the builder stash the WinRMPassword in the state bag, then
|
||||
// grabbing it out of the statebag inside of StepProvision. Then, when
|
||||
// the time comes to provision for real, we run the prepare step one more
|
||||
// time, now with WinRMPassword defined in the raws, and can store the
|
||||
// password on the provisioner config without overwriting the rest of the
|
||||
// work we've already done in the first prepare run.
|
||||
if len(raws) == 1 {
|
||||
for k, v := range raws[0].(map[interface{}]interface{}) {
|
||||
if k.(string) == "WinRMPassword" {
|
||||
p.config.WinRMPassword = v.(string)
|
||||
// Even if WinRMPassword is not gonna be used, we've stored the
|
||||
// key and pointed it to an empty string. That means we'll
|
||||
// always reach this on our second-run of Prepare()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := sl.Decode(&p.config, raws...)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -48,8 +48,8 @@ func TestConfigPrepare(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testConfig(t *testing.T) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
func testConfig(t *testing.T) map[interface{}]interface{} {
|
||||
return map[interface{}]interface{}{
|
||||
"command": "echo foo",
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue