add a configurable pause before step_connect to work around bootstrap race conditions

This commit is contained in:
Megan Marsh 2019-02-15 15:05:29 -08:00
parent 9b69790514
commit 31c8acc5bc
3 changed files with 42 additions and 0 deletions

View File

@ -66,6 +66,9 @@ type Config struct {
WinRMInsecure bool `mapstructure:"winrm_insecure"`
WinRMUseNTLM bool `mapstructure:"winrm_use_ntlm"`
WinRMTransportDecorator func() winrm.Transporter
// Delay
PauseBeforeConnect time.Duration `mapstructure:"pause_before_connecting"`
}
// ReadSSHPrivateKeyFile returns the SSH private key bytes

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"time"
"github.com/hashicorp/packer/communicator/none"
"github.com/hashicorp/packer/helper/multistep"
@ -44,9 +45,28 @@ type StepConnect struct {
substep multistep.Step
}
func (s *StepConnect) pause(pauseLen time.Duration, ctx context.Context) bool {
// Use a select to determine if we get cancelled during the wait
log.Printf("Pausing before connecting...")
select {
case <-ctx.Done():
return true
case <-time.After(pauseLen):
}
log.Printf("Pause over; connecting...")
return false
}
func (s *StepConnect) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
if s.Config.PauseBeforeConnect > 0 {
cancelled := s.pause(s.Config.PauseBeforeConnect, ctx)
if cancelled {
return multistep.ActionHalt
}
}
typeMap := map[string]multistep.Step{
"none": nil,
"ssh": &StepConnectSSH{

View File

@ -198,3 +198,22 @@ The WinRM communicator has the following options.
- `winrm_use_ssl` (boolean) - If `true`, use HTTPS for WinRM.
- `winrm_username` (string) - The username to use to connect to WinRM.
## Pausing Before Connecting
We recommend that you enable SSH or WinRM as the very last step in your
guest's bootstrap script, but sometimes you may have a race condition where
you need Packer to wait before attempting to connect to your guest.
If you end up in this situation, you can use the template option
`pause_before_connecting`. By default, there is no pause. For example:
{
"communicator": "ssh"
"ssh_username": "myuser",
"pause_before_connecting": "10m"
}
In this example, Packer will wait 10 minutes before attempting to connect to
the guest.