pass struct of generated data into provision() call

This commit is contained in:
Megan Marsh 2019-07-11 09:37:59 -07:00
parent 5e81c6f44e
commit f4c3501af5
23 changed files with 78 additions and 56 deletions

View File

@ -23,6 +23,17 @@ type StepProvision struct {
Comm packer.Communicator
}
func PopulateProvisionHookData(state multistep.StateBag) packer.ProvisionHookData {
hookData := packer.NewProvisionHookData()
// Add WinRMPassword to runtime data
WinRMPassword, ok := state.GetOk("winrm_password")
if ok {
hookData.WinRMPassword = WinRMPassword.(string)
}
return hookData
}
func (s *StepProvision) runWithHook(ctx context.Context, state multistep.StateBag, hooktype string) multistep.StepAction {
// hooktype will be either packer.HookProvision or packer.HookCleanupProvision
comm := s.Comm
@ -32,9 +43,12 @@ func (s *StepProvision) runWithHook(ctx context.Context, state multistep.StateBa
comm = raw.(packer.Communicator)
}
}
hook := state.Get("hook").(packer.Hook)
ui := state.Get("ui").(packer.Ui)
hookData := PopulateProvisionHookData(state)
// Run the provisioner in a goroutine so we can continually check
// for cancellations...
if hooktype == packer.HookProvision {
@ -44,7 +58,7 @@ func (s *StepProvision) runWithHook(ctx context.Context, state multistep.StateBa
}
errCh := make(chan error, 1)
go func() {
errCh <- hook.Run(ctx, hooktype, ui, comm, nil)
errCh <- hook.Run(ctx, hooktype, ui, comm, &hookData)
}()
for {

View File

@ -21,13 +21,13 @@ func (c *cmdProvisioner) Prepare(configs ...interface{}) error {
return c.p.Prepare(configs...)
}
func (c *cmdProvisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (c *cmdProvisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData *packer.ProvisionHookData) error {
defer func() {
r := recover()
c.checkExit(r, nil)
}()
return c.p.Provision(ctx, ui, comm)
return c.p.Provision(ctx, ui, comm, generatedData)
}
func (c *cmdProvisioner) checkExit(p interface{}, cb func()) {

View File

@ -20,7 +20,7 @@ type Provisioner interface {
// given for cancellation, a UI is given to communicate with the user, and
// a communicator is given that is guaranteed to be connected to some
// machine so that provisioning can be done.
Provision(context.Context, Ui, Communicator) error
Provision(context.Context, Ui, Communicator, *ProvisionHookData) error
}
// A HookedProvisioner represents a provisioner and information describing it
@ -37,6 +37,21 @@ type ProvisionHook struct {
Provisioners []*HookedProvisioner
}
type ProvisionHookData struct {
WinRMPassword string
}
func NewProvisionHookData() ProvisionHookData {
// this is the function we use to create the provisionhookdata, and as a
// bonus the initialized state applies defaults that act as passthroughs so
// that when prepare is called the first time, we can save interpolating
// these values until provisioner run time.
hookData := ProvisionHookData{
WinRMPassword: `{{.WinRMPassword}}`,
}
return hookData
}
// Runs the provisioners in order.
func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Communicator, data interface{}) error {
// Shortcut
@ -44,6 +59,11 @@ func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Commun
return nil
}
generatedData := NewProvisionHookData()
if data != nil {
generatedData = data.(ProvisionHookData)
}
if comm == nil {
return fmt.Errorf(
"No communicator found for provisioners! This is usually because the\n" +
@ -53,7 +73,7 @@ func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Commun
for _, p := range h.Provisioners {
ts := CheckpointReporter.AddSpan(p.TypeName, "provisioner", p.Config)
err := p.Provisioner.Provision(ctx, ui, comm)
err := p.Provisioner.Provision(ctx, ui, comm, &generatedData)
ts.End(err)
if err != nil {
@ -75,7 +95,7 @@ func (p *PausedProvisioner) Prepare(raws ...interface{}) error {
return p.Provisioner.Prepare(raws...)
}
func (p *PausedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error {
func (p *PausedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData *ProvisionHookData) error {
// Use a select to determine if we get cancelled during the wait
ui.Say(fmt.Sprintf("Pausing %s before the next provisioner...", p.PauseBefore))
@ -85,7 +105,7 @@ func (p *PausedProvisioner) Provision(ctx context.Context, ui Ui, comm Communica
return ctx.Err()
}
return p.Provisioner.Provision(ctx, ui, comm)
return p.Provisioner.Provision(ctx, ui, comm, generatedData)
}
// DebuggedProvisioner is a Provisioner implementation that waits until a key
@ -102,7 +122,7 @@ func (p *DebuggedProvisioner) Prepare(raws ...interface{}) error {
return p.Provisioner.Prepare(raws...)
}
func (p *DebuggedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error {
func (p *DebuggedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData *ProvisionHookData) error {
// Use a select to determine if we get cancelled during the wait
message := "Pausing before the next provisioner . Press enter to continue."
@ -122,5 +142,5 @@ func (p *DebuggedProvisioner) Provision(ctx context.Context, ui Ui, comm Communi
return ctx.Err()
}
return p.Provisioner.Provision(ctx, ui, comm)
return p.Provisioner.Provision(ctx, ui, comm, generatedData)
}

View File

@ -22,7 +22,7 @@ func (t *MockProvisioner) Prepare(configs ...interface{}) error {
return nil
}
func (t *MockProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error {
func (t *MockProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData *ProvisionHookData) error {
t.ProvCalled = true
t.ProvCommunicator = comm
t.ProvUi = ui

View File

@ -13,7 +13,7 @@ type TimeoutProvisioner struct {
Timeout time.Duration
}
func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error {
func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData *ProvisionHookData) error {
ctx, cancel := context.WithTimeout(ctx, p.Timeout)
defer cancel()
@ -37,7 +37,7 @@ func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communic
}
}()
err := p.Provisioner.Provision(ctx, ui, comm)
err := p.Provisioner.Provision(ctx, ui, comm, generatedData)
close(errC)
return err
}

View File

@ -38,7 +38,7 @@ func (p *provisioner) Prepare(configs ...interface{}) (err error) {
return
}
func (p *provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData *packer.ProvisionHookData) error {
nextId := p.mux.NextId()
server := newServerWithMux(p.mux, nextId)
server.RegisterCommunicator(comm)
@ -66,7 +66,7 @@ func (p *ProvisionerServer) Prepare(args *ProvisionerPrepareArgs, reply *interfa
return p.p.Prepare(args.Configs...)
}
func (p *ProvisionerServer) Provision(streamId uint32, reply *interface{}) error {
func (p *ProvisionerServer) Provision(streamId uint32, reply *interface{}, generatedData *packer.ProvisionHookData) error {
client, err := newClientWithMux(p.mux, streamId)
if err != nil {
return NewBasicError(err)
@ -77,7 +77,7 @@ func (p *ProvisionerServer) Provision(streamId uint32, reply *interface{}) error
p.context, p.contextCancel = context.WithCancel(context.Background())
}
if err := p.p.Provision(p.context, client.Ui(), client.Communicator()); err != nil {
if err := p.p.Provision(p.context, client.Ui(), client.Communicator(), generatedData); err != nil {
return NewBasicError(err)
}

View File

@ -188,7 +188,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with Ansible...")
if len(p.config.PlaybookDir) > 0 {

View File

@ -214,7 +214,7 @@ func (p *Provisioner) getVersion() error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with Ansible...")
// Interpolate env vars to check for .WinRMPassword
p.config.ctx.Data = &PassthroughTemplate{

View File

@ -42,7 +42,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
if p.config.Disable {
if p.config.Note != "" {
ui.Say(fmt.Sprintf(

View File

@ -244,7 +244,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
p.communicator = comm

View File

@ -238,7 +238,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with chef-solo")
if !p.config.SkipInstall {

View File

@ -108,7 +108,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
}
// Provision node somehow. TODO: actual docs
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with Converge")
// bootstrapping

View File

@ -92,7 +92,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
if p.config.Direction == "download" {
return p.ProvisionDownload(ui, comm)
} else {

View File

@ -186,7 +186,7 @@ func (p *Provisioner) getVersion() error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with Inspec...")
for i, envVar := range p.config.InspecEnvVars {

View File

@ -20,7 +20,6 @@ import (
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/common/shell"
"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/packer/tmp"
@ -73,8 +72,9 @@ type Config struct {
}
type Provisioner struct {
config Config
communicator packer.Communicator
config Config
communicator packer.Communicator
generatedData *packer.ProvisionHookData
}
type ExecuteCommandTemplate struct {
@ -83,10 +83,6 @@ type ExecuteCommandTemplate struct {
WinRMPassword string
}
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'};` +
@ -101,9 +97,7 @@ func (p *Provisioner) defaultExecuteCommand() string {
func (p *Provisioner) Prepare(raws ...interface{}) error {
// Create passthrough for winrm password so we can fill it in once we know
// it
p.config.ctx.Data = &EnvVarsTemplate{
WinRMPassword: `{{.WinRMPassword}}`,
}
p.config.ctx.Data = packer.NewProvisionHookData()
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
@ -232,9 +226,12 @@ func extractScript(p *Provisioner) (string, error) {
return temp.Name(), nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData *packer.ProvisionHookData) error {
ui.Say(fmt.Sprintf("Provisioning with Powershell..."))
p.communicator = comm
p.generatedData = generatedData
packer.LogSecretFilter.Set(p.generatedData.WinRMPassword)
scripts := make([]string, len(p.config.Scripts))
copy(scripts, p.config.Scripts)
@ -344,9 +341,8 @@ func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) {
}
// interpolate environment variables
p.config.ctx.Data = &EnvVarsTemplate{
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
}
p.config.ctx.Data = p.generatedData
// Split vars into key/value components
for _, envVar := range p.config.Vars {
envVar, err := interpolate.Render(envVar, &p.config.ctx)
@ -421,7 +417,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.generatedData.WinRMPassword,
}
command, err = interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
@ -433,12 +429,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
@ -450,7 +440,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.generatedData.WinRMPassword,
}
command, err = interpolate.Render(p.config.ElevatedExecuteCommand, &p.config.ctx)
if err != nil {
@ -475,9 +465,7 @@ func (p *Provisioner) ElevatedUser() string {
func (p *Provisioner) ElevatedPassword() string {
// Replace ElevatedPassword for winrm users who used this feature
p.config.ctx.Data = &EnvVarsTemplate{
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
}
p.config.ctx.Data = p.generatedData
elevatedPassword, _ := interpolate.Render(p.config.ElevatedPassword, &p.config.ctx)

View File

@ -259,7 +259,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with Puppet...")
p.communicator = comm
ui.Message("Creating Puppet staging directory...")

View File

@ -229,7 +229,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say("Provisioning with Puppet...")
p.communicator = comm
ui.Message("Creating Puppet staging directory...")

View File

@ -222,7 +222,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
var err error
var src, dst string

View File

@ -25,7 +25,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, _ packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, _ packer.Communicator, _ *packer.ProvisionHookData) error {
_, retErr := sl.Run(ctx, ui, &p.config)
return retErr

View File

@ -179,7 +179,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
scripts := make([]string, len(p.config.Scripts))
copy(scripts, p.config.Scripts)

View File

@ -20,7 +20,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return config.Decode(&p, &config.DecodeOpts{}, raws...)
}
func (p *Provisioner) Provision(ctx context.Context, _ packer.Ui, _ packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, _ packer.Ui, _ packer.Communicator, _ *packer.ProvisionHookData) error {
select {
case <-ctx.Done():
return ctx.Err()

View File

@ -96,7 +96,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
return nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
p.cancelLock.Lock()
p.cancel = make(chan struct{})
p.cancelLock.Unlock()

View File

@ -156,7 +156,7 @@ func extractScript(p *Provisioner) (string, error) {
return temp.Name(), nil
}
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ *packer.ProvisionHookData) error {
ui.Say(fmt.Sprintf("Provisioning with windows-shell..."))
scripts := make([]string, len(p.config.Scripts))
copy(scripts, p.config.Scripts)