diff --git a/helper/communicator/config.go b/helper/communicator/config.go index 7d66254b5..fa02810d7 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -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 diff --git a/helper/communicator/step_connect.go b/helper/communicator/step_connect.go index 10adc5d2b..6cab6e004 100644 --- a/helper/communicator/step_connect.go +++ b/helper/communicator/step_connect.go @@ -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{ diff --git a/website/source/docs/templates/communicator.html.md b/website/source/docs/templates/communicator.html.md index c8054f623..42a4c2e94 100644 --- a/website/source/docs/templates/communicator.html.md +++ b/website/source/docs/templates/communicator.html.md @@ -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. + +