diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index ac128e899..228ad52f6 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -9,10 +9,10 @@ import ( "os" "regexp" "strings" + "time" "github.com/hashicorp/packer/common/uuid" "github.com/hashicorp/packer/helper/communicator" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/template/interpolate" ) @@ -371,7 +371,7 @@ type RunConfig struct { // The timeout for waiting for a Windows // password for Windows instances. Defaults to 20 minutes. Example value: // 10m - WindowsPasswordTimeout config.DurationString `mapstructure:"windows_password_timeout" required:"false"` + WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout" required:"false"` // Communicator settings Comm communicator.Config `mapstructure:",squash"` @@ -389,8 +389,8 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { c.Comm.SSHTemporaryKeyPairName = fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID()) } - if c.WindowsPasswordTimeout == "" { - c.WindowsPasswordTimeout = "20m" + if c.WindowsPasswordTimeout == 0 { + c.WindowsPasswordTimeout = 20 * time.Minute } if c.RunTags == nil { diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index e312241b3..d2638d806 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -229,7 +229,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &awscommon.StepGetPassword{ Debug: b.config.PackerDebug, Comm: &b.config.RunConfig.Comm, - Timeout: b.config.WindowsPasswordTimeout.Duration(), + Timeout: b.config.WindowsPasswordTimeout, BuildName: b.config.PackerBuildName, }, &communicator.StepConnect{ diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index 5c45eef93..3e65bd6c4 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -271,7 +271,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &awscommon.StepGetPassword{ Debug: b.config.PackerDebug, Comm: &b.config.RunConfig.Comm, - Timeout: b.config.WindowsPasswordTimeout.Duration(), + Timeout: b.config.WindowsPasswordTimeout, BuildName: b.config.PackerBuildName, }, &communicator.StepConnect{ diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index 4640b8836..5ed61279e 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -237,7 +237,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &awscommon.StepGetPassword{ Debug: b.config.PackerDebug, Comm: &b.config.RunConfig.Comm, - Timeout: b.config.WindowsPasswordTimeout.Duration(), + Timeout: b.config.WindowsPasswordTimeout, BuildName: b.config.PackerBuildName, }, &communicator.StepConnect{ diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 481052727..78ccbdd1a 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -322,7 +322,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &awscommon.StepGetPassword{ Debug: b.config.PackerDebug, Comm: &b.config.RunConfig.Comm, - Timeout: b.config.WindowsPasswordTimeout.Duration(), + Timeout: b.config.WindowsPasswordTimeout, BuildName: b.config.PackerBuildName, }, &communicator.StepConnect{ diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go index fd1f9b196..2a06f1b84 100644 --- a/builder/azure/arm/builder.go +++ b/builder/azure/arm/builder.go @@ -80,8 +80,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack b.config.ResourceGroupName, b.config.StorageAccount, b.config.ClientConfig.CloudEnvironment(), - b.config.SharedGalleryTimeout.Duration(), - b.config.PollingDurationTimeout.Duration(), + b.config.SharedGalleryTimeout, + b.config.PollingDurationTimeout, spnCloud, spnKeyVault) diff --git a/builder/azure/arm/config.go b/builder/azure/arm/config.go index f1d5cfcb9..552a2389d 100644 --- a/builder/azure/arm/config.go +++ b/builder/azure/arm/config.go @@ -139,7 +139,7 @@ type Config struct { // Azure dashboard, then you probably need to increase this timeout from // its default of "60m" (valid time units include `s` for seconds, `m` for // minutes, and `h` for hours.) - SharedGalleryTimeout config.DurationString `mapstructure:"shared_image_gallery_timeout"` + SharedGalleryTimeout time.Duration `mapstructure:"shared_image_gallery_timeout"` // PublisherName for your base image. See // [documentation](https://azure.microsoft.com/en-us/documentation/articles/resource-groups-vm-searching/) // for details. @@ -320,7 +320,7 @@ type Config struct { // context deadline exceeded`, then you probably need to increase this timeout from // its default of "15m" (valid time units include `s` for seconds, `m` for // minutes, and `h` for hours.) - PollingDurationTimeout config.DurationString `mapstructure:"polling_duration_timeout" required:"false"` + PollingDurationTimeout time.Duration `mapstructure:"polling_duration_timeout" required:"false"` // If either Linux or Windows is specified Packer will // automatically configure authentication credentials for the provisioned // machine. For Linux this configures an SSH authorized key. For Windows @@ -550,8 +550,8 @@ func newConfig(raws ...interface{}) (*Config, []string, error) { } func setSshValues(c *Config) error { - if c.Comm.SSHTimeout == "" { - c.Comm.SSHTimeout = "20m" + if c.Comm.SSHTimeout == 0 { + c.Comm.SSHTimeout = 20 * time.Minute } if c.Comm.SSHPrivateKeyFile != "" { @@ -867,9 +867,9 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) { errs = packer.MultiErrorAppend(errs, fmt.Errorf("A list of replication_regions must be specified for shared_image_gallery_destination")) } } - if c.SharedGalleryTimeout == "" { + if c.SharedGalleryTimeout == 0 { // default to a one-hour timeout. In the sdk, the default is 15 m. - c.SharedGalleryTimeout = "60m" + c.SharedGalleryTimeout = 60 * time.Minute } if c.ManagedImageOSDiskSnapshotName != "" { @@ -920,9 +920,9 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) { ///////////////////////////////////////////// // Polling Duration Timeout - if c.PollingDurationTimeout == "" { + if c.PollingDurationTimeout == 0 { // In the sdk, the default is 15 m. - c.PollingDurationTimeout = "15m" + c.PollingDurationTimeout = 15 * time.Minute } ///////////////////////////////////////////// diff --git a/builder/azure/arm/config_test.go b/builder/azure/arm/config_test.go index b229fbdb9..52ad4814e 100644 --- a/builder/azure/arm/config_test.go +++ b/builder/azure/arm/config_test.go @@ -539,11 +539,11 @@ func TestConfigShouldSupportPackersConfigElements(t *testing.T) { t.Fatal(err) } - if c.Comm.SSHTimeout.Duration() != 1*time.Hour { + if c.Comm.SSHTimeout != 1*time.Hour { t.Errorf("Expected Comm.SSHTimeout to be a duration of an hour, but got '%s' instead.", c.Comm.SSHTimeout) } - if c.Comm.WinRMTimeout.Duration() != 2*time.Hour { + if c.Comm.WinRMTimeout != 2*time.Hour { t.Errorf("Expected Comm.WinRMTimeout to be a durationof two hours, but got '%s' instead.", c.Comm.WinRMTimeout) } } diff --git a/builder/cloudstack/builder.go b/builder/cloudstack/builder.go index dedc70e83..dc1dace69 100644 --- a/builder/cloudstack/builder.go +++ b/builder/cloudstack/builder.go @@ -44,7 +44,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack ) // Set the time to wait before timing out - client.AsyncTimeout(int64(b.config.AsyncTimeout.Duration().Seconds())) + client.AsyncTimeout(int64(b.config.AsyncTimeout.Seconds())) // Some CloudStack service providers only allow HTTP GET calls. client.HTTPGETOnly = b.config.HTTPGetOnly diff --git a/builder/cloudstack/config.go b/builder/cloudstack/config.go index 0831b8f4c..cff9e2472 100644 --- a/builder/cloudstack/config.go +++ b/builder/cloudstack/config.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "os" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/uuid" @@ -34,7 +35,7 @@ type Config struct { SecretKey string `mapstructure:"secret_key" required:"true"` // The time duration to wait for async calls to // finish. Defaults to 30m. - AsyncTimeout config.DurationString `mapstructure:"async_timeout" required:"false"` + AsyncTimeout time.Duration `mapstructure:"async_timeout" required:"false"` // Some cloud providers only allow HTTP GET calls // to their CloudStack API. If using such a provider, you need to set this to // true in order for the provider to only make GET calls and no POST calls. @@ -67,7 +68,7 @@ type Config struct { // Configure the duration time to wait, making sure virtual machine is able // to finish installing OS before it ejects safely. Requires `eject_iso` // set to `true` and this option is only available when using `source_iso`. - EjectISODelay config.DurationString `mapstructure:"eject_iso_delay"` + EjectISODelay time.Duration `mapstructure:"eject_iso_delay"` // Set to true to expunge the instance when it is // destroyed. Defaults to false. Expunge bool `mapstructure:"expunge" required:"false"` @@ -199,8 +200,8 @@ func NewConfig(raws ...interface{}) (*Config, error) { c.SecretKey = os.Getenv("CLOUDSTACK_SECRET_KEY") } - if c.AsyncTimeout == "" { - c.AsyncTimeout = "30m" + if c.AsyncTimeout == 0 { + c.AsyncTimeout = 30 * time.Minute } if len(c.CIDRList) == 0 { diff --git a/builder/cloudstack/step_detach_iso.go b/builder/cloudstack/step_detach_iso.go index 748f139a8..444293c2c 100644 --- a/builder/cloudstack/step_detach_iso.go +++ b/builder/cloudstack/step_detach_iso.go @@ -25,9 +25,9 @@ func (s *stepDetachIso) Run(ctx context.Context, state multistep.StateBag) multi ui.Say("Checking attached iso...") // Wait to make call detachIso - if config.EjectISODelay.Duration() > 0 { + if config.EjectISODelay > 0 { ui.Message(fmt.Sprintf("Waiting for %v before detaching ISO from virtual machine...", config.EjectISODelay)) - time.Sleep(config.EjectISODelay.Duration()) + time.Sleep(config.EjectISODelay) } client := state.Get("client").(*cloudstack.CloudStackClient) diff --git a/builder/digitalocean/builder.go b/builder/digitalocean/builder.go index 1b3cdb23d..661e2c2a4 100644 --- a/builder/digitalocean/builder.go +++ b/builder/digitalocean/builder.go @@ -96,7 +96,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack new(stepShutdown), new(stepPowerOff), &stepSnapshot{ - snapshotTimeout: b.config.SnapshotTimeout.Duration(), + snapshotTimeout: b.config.SnapshotTimeout, }, } diff --git a/builder/digitalocean/builder_test.go b/builder/digitalocean/builder_test.go index 02db72d25..70ec6fea9 100644 --- a/builder/digitalocean/builder_test.go +++ b/builder/digitalocean/builder_test.go @@ -165,7 +165,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) { t.Fatalf("should not have error: %s", err) } - if b.config.StateTimeout.Duration() != 6*time.Minute { + if b.config.StateTimeout != 6*time.Minute { t.Errorf("invalid: %s", b.config.StateTimeout) } @@ -205,7 +205,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) { t.Fatalf("should not have error: %s", err) } - if b.config.SnapshotTimeout.Duration() != 60*time.Minute { + if b.config.SnapshotTimeout != 60*time.Minute { t.Errorf("invalid: %s", b.config.SnapshotTimeout) } diff --git a/builder/digitalocean/config.go b/builder/digitalocean/config.go index 832818a7e..b087cdb9e 100644 --- a/builder/digitalocean/config.go +++ b/builder/digitalocean/config.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "regexp" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/uuid" @@ -63,7 +64,7 @@ type Config struct { // The time to wait, as a duration string, for a // droplet to enter a desired state (such as "active") before timing out. The // default state timeout is "6m". - StateTimeout config.DurationString `mapstructure:"state_timeout" required:"false"` + StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"` // How long to wait for an image to be published to the shared image // gallery before timing out. If your Packer build is failing on the // Publishing to Shared Image Gallery step with the error `Original Error: @@ -71,7 +72,7 @@ type Config struct { // Azure dashboard, then you probably need to increase this timeout from // its default of "60m" (valid time units include `s` for seconds, `m` for // minutes, and `h` for hours.) - SnapshotTimeout config.DurationString `mapstructure:"snapshot_timeout" required:"false"` + SnapshotTimeout time.Duration `mapstructure:"snapshot_timeout" required:"false"` // The name assigned to the droplet. DigitalOcean // sets the hostname of the machine to this value. DropletName string `mapstructure:"droplet_name" required:"false"` @@ -129,27 +130,19 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.DropletName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID()) } - if c.StateTimeout == "" { + if c.StateTimeout == 0 { // Default to 6 minute timeouts waiting for // desired state. i.e waiting for droplet to become active - c.StateTimeout = "6m" + c.StateTimeout = 6 * time.Minute } - if c.SnapshotTimeout == "" { + if c.SnapshotTimeout == 0 { // Default to 60 minutes timeout, waiting for snapshot action to finish - c.SnapshotTimeout = "60m" + c.SnapshotTimeout = 60 * time.Minute } var errs *packer.MultiError - if err := c.StateTimeout.Validate(); err != nil { - errs = packer.MultiErrorAppend(errs, err) - } - - if err := c.SnapshotTimeout.Validate(); err != nil { - errs = packer.MultiErrorAppend(errs, err) - } - if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { errs = packer.MultiErrorAppend(errs, es...) } diff --git a/builder/digitalocean/step_droplet_info.go b/builder/digitalocean/step_droplet_info.go index b7ff1d19f..dc7a9ed8a 100644 --- a/builder/digitalocean/step_droplet_info.go +++ b/builder/digitalocean/step_droplet_info.go @@ -19,7 +19,7 @@ func (s *stepDropletInfo) Run(ctx context.Context, state multistep.StateBag) mul ui.Say("Waiting for droplet to become active...") - err := waitForDropletState("active", dropletID, client, c.StateTimeout.Duration()) + err := waitForDropletState("active", dropletID, client, c.StateTimeout) if err != nil { err := fmt.Errorf("Error waiting for droplet to become active: %s", err) state.Put("error", err) diff --git a/builder/digitalocean/step_power_off.go b/builder/digitalocean/step_power_off.go index a9248efbb..fab35569a 100644 --- a/builder/digitalocean/step_power_off.go +++ b/builder/digitalocean/step_power_off.go @@ -42,7 +42,7 @@ func (s *stepPowerOff) Run(ctx context.Context, state multistep.StateBag) multis } log.Println("Waiting for poweroff event to complete...") - err = waitForDropletState("off", dropletId, client, c.StateTimeout.Duration()) + err = waitForDropletState("off", dropletId, client, c.StateTimeout) if err != nil { state.Put("error", err) ui.Error(err.Error()) @@ -50,7 +50,7 @@ func (s *stepPowerOff) Run(ctx context.Context, state multistep.StateBag) multis } // Wait for the droplet to become unlocked for future steps - if err := waitForDropletUnlocked(client, dropletId, c.StateTimeout.Duration()); err != nil { + if err := waitForDropletUnlocked(client, dropletId, c.StateTimeout); err != nil { // If we get an error the first time, actually report it err := fmt.Errorf("Error powering off droplet: %s", err) state.Put("error", err) diff --git a/builder/digitalocean/step_shutdown.go b/builder/digitalocean/step_shutdown.go index 120d90a0c..339e034b7 100644 --- a/builder/digitalocean/step_shutdown.go +++ b/builder/digitalocean/step_shutdown.go @@ -65,7 +65,7 @@ func (s *stepShutdown) Run(ctx context.Context, state multistep.StateBag) multis } }() - err = waitForDropletState("off", dropletId, client, c.StateTimeout.Duration()) + err = waitForDropletState("off", dropletId, client, c.StateTimeout) if err != nil { // If we get an error the first time, actually report it err := fmt.Errorf("Error shutting down droplet: %s", err) @@ -74,7 +74,7 @@ func (s *stepShutdown) Run(ctx context.Context, state multistep.StateBag) multis return multistep.ActionHalt } - if err := waitForDropletUnlocked(client, dropletId, c.StateTimeout.Duration()); err != nil { + if err := waitForDropletUnlocked(client, dropletId, c.StateTimeout); err != nil { // If we get an error the first time, actually report it err := fmt.Errorf("Error shutting down droplet: %s", err) state.Put("error", err) diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index b1b85563f..7aeeb4cb5 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "regexp" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/uuid" @@ -120,7 +121,7 @@ type Config struct { // If true, launch a preemptible instance. Preemptible bool `mapstructure:"preemptible" required:"false"` // The time to wait for instance state changes. Defaults to "5m". - StateTimeout config.DurationString `mapstructure:"state_timeout" required:"false"` + StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"` // The region in which to launch the instance. Defaults to the region // hosting the specified zone. Region string `mapstructure:"region" required:"false"` @@ -291,12 +292,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.MachineType = "n1-standard-1" } - if c.StateTimeout == "" { - c.StateTimeout = "5m" - } - - if err := c.StateTimeout.Validate(); err != nil { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing state_timeout: %s", err)) + if c.StateTimeout == 0 { + c.StateTimeout = 5 * time.Minute } if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { diff --git a/builder/googlecompute/step_create_image.go b/builder/googlecompute/step_create_image.go index 51aeb9264..62106d60b 100644 --- a/builder/googlecompute/step_create_image.go +++ b/builder/googlecompute/step_create_image.go @@ -44,7 +44,7 @@ func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul var err error select { case err = <-errCh: - case <-time.After(config.StateTimeout.Duration()): + case <-time.After(config.StateTimeout): err = errors.New("time out while waiting for image to register") } diff --git a/builder/googlecompute/step_create_instance.go b/builder/googlecompute/step_create_instance.go index a0bd48d3a..ca15eeccb 100644 --- a/builder/googlecompute/step_create_instance.go +++ b/builder/googlecompute/step_create_instance.go @@ -154,7 +154,7 @@ func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag) ui.Message("Waiting for creation operation to complete...") select { case err = <-errCh: - case <-time.After(c.StateTimeout.Duration()): + case <-time.After(c.StateTimeout): err = errors.New("time out while waiting for instance to create") } } @@ -200,7 +200,7 @@ func (s *StepCreateInstance) Cleanup(state multistep.StateBag) { if err == nil { select { case err = <-errCh: - case <-time.After(config.StateTimeout.Duration()): + case <-time.After(config.StateTimeout): err = errors.New("time out while waiting for instance to delete") } } @@ -222,7 +222,7 @@ func (s *StepCreateInstance) Cleanup(state multistep.StateBag) { if err == nil { select { case err = <-errCh: - case <-time.After(config.StateTimeout.Duration()): + case <-time.After(config.StateTimeout): err = errors.New("time out while waiting for disk to delete") } } diff --git a/builder/googlecompute/step_create_instance_test.go b/builder/googlecompute/step_create_instance_test.go index 0065255dc..c107f4530 100644 --- a/builder/googlecompute/step_create_instance_test.go +++ b/builder/googlecompute/step_create_instance_test.go @@ -5,6 +5,7 @@ import ( "errors" "strings" "testing" + "time" "github.com/hashicorp/packer/helper/multistep" "github.com/stretchr/testify/assert" @@ -231,7 +232,7 @@ func TestStepCreateInstance_errorTimeout(t *testing.T) { errCh := make(chan error, 1) config := state.Get("config").(*Config) - config.StateTimeout = "1ms" + config.StateTimeout = 1 * time.Millisecond d := state.Get("driver").(*DriverMock) d.RunInstanceErrCh = errCh diff --git a/builder/googlecompute/step_create_windows_password.go b/builder/googlecompute/step_create_windows_password.go index 60a0d2fa0..2112b843c 100644 --- a/builder/googlecompute/step_create_windows_password.go +++ b/builder/googlecompute/step_create_windows_password.go @@ -99,7 +99,7 @@ func (s *StepCreateWindowsPassword) Run(ctx context.Context, state multistep.Sta ui.Message("Waiting for windows password to complete...") select { case err = <-errCh: - case <-time.After(c.StateTimeout.Duration()): + case <-time.After(c.StateTimeout): err = errors.New("time out while waiting for the password to be created") } } diff --git a/builder/googlecompute/step_instance_info.go b/builder/googlecompute/step_instance_info.go index d419b8cfd..b36d2f1d8 100644 --- a/builder/googlecompute/step_instance_info.go +++ b/builder/googlecompute/step_instance_info.go @@ -29,7 +29,7 @@ func (s *StepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) mu var err error select { case err = <-errCh: - case <-time.After(config.StateTimeout.Duration()): + case <-time.After(config.StateTimeout): err = errors.New("time out while waiting for instance to become running") } diff --git a/builder/googlecompute/step_instance_info_test.go b/builder/googlecompute/step_instance_info_test.go index 6cad9a06d..7435df7fc 100644 --- a/builder/googlecompute/step_instance_info_test.go +++ b/builder/googlecompute/step_instance_info_test.go @@ -156,7 +156,7 @@ func TestStepInstanceInfo_errorTimeout(t *testing.T) { state.Put("instance_name", "foo") config := state.Get("config").(*Config) - config.StateTimeout = "1ms" + config.StateTimeout = 1 * time.Millisecond driver := state.Get("driver").(*DriverMock) driver.WaitForInstanceErrCh = errCh diff --git a/builder/googlecompute/step_teardown_instance.go b/builder/googlecompute/step_teardown_instance.go index ae3c13ec2..e7757862b 100644 --- a/builder/googlecompute/step_teardown_instance.go +++ b/builder/googlecompute/step_teardown_instance.go @@ -34,7 +34,7 @@ func (s *StepTeardownInstance) Run(ctx context.Context, state multistep.StateBag if err == nil { select { case err = <-errCh: - case <-time.After(config.StateTimeout.Duration()): + case <-time.After(config.StateTimeout): err = errors.New("time out while waiting for instance to delete") } } @@ -64,7 +64,7 @@ func (s *StepTeardownInstance) Cleanup(state multistep.StateBag) { if err == nil { select { case err = <-errCh: - case <-time.After(config.StateTimeout.Duration()): + case <-time.After(config.StateTimeout): err = errors.New("time out while waiting for disk to delete") } } diff --git a/builder/hcloud/builder.go b/builder/hcloud/builder.go index 28b7e3489..92f9f474b 100644 --- a/builder/hcloud/builder.go +++ b/builder/hcloud/builder.go @@ -35,7 +35,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack opts := []hcloud.ClientOption{ hcloud.WithToken(b.config.HCloudToken), hcloud.WithEndpoint(b.config.Endpoint), - hcloud.WithPollInterval(b.config.PollInterval.Duration()), + hcloud.WithPollInterval(b.config.PollInterval), hcloud.WithApplication("hcloud-packer", pluginVersion), } b.hcloudClient = hcloud.NewClient(opts...) diff --git a/builder/hcloud/config.go b/builder/hcloud/config.go index 1fe711079..6e8b56ba6 100644 --- a/builder/hcloud/config.go +++ b/builder/hcloud/config.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "os" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/uuid" @@ -25,7 +26,7 @@ type Config struct { HCloudToken string `mapstructure:"token"` Endpoint string `mapstructure:"endpoint"` - PollInterval config.DurationString `mapstructure:"poll_interval"` + PollInterval time.Duration `mapstructure:"poll_interval"` ServerName string `mapstructure:"server_name"` Location string `mapstructure:"location"` @@ -78,8 +79,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.Endpoint = hcloud.Endpoint } } - if c.PollInterval == "" { - c.PollInterval = "500ms" + if c.PollInterval == 0 { + c.PollInterval = 500 * time.Millisecond } if c.SnapshotName == "" { diff --git a/builder/hyperone/builder.go b/builder/hyperone/builder.go index e2e0c27b5..d9e85e5f0 100644 --- a/builder/hyperone/builder.go +++ b/builder/hyperone/builder.go @@ -38,7 +38,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { cfg.BasePath = b.config.APIURL } - prefer := fmt.Sprintf("respond-async,wait=%d", int(b.config.StateTimeout.Duration().Seconds())) + prefer := fmt.Sprintf("respond-async,wait=%d", int(b.config.StateTimeout.Seconds())) cfg.AddDefaultHeader("Prefer", prefer) b.client = openapi.NewAPIClient(cfg) diff --git a/builder/hyperone/config.go b/builder/hyperone/config.go index 7833007fc..f9173f7ce 100644 --- a/builder/hyperone/config.go +++ b/builder/hyperone/config.go @@ -8,6 +8,7 @@ import ( "fmt" "io/ioutil" "os" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/json" @@ -27,7 +28,7 @@ const ( defaultDiskType = "ssd" defaultImageService = "564639bc052c084e2f2e3266" - defaultStateTimeout = "5m" + defaultStateTimeout = 5 * time.Minute defaultUserName = "guru" ) @@ -50,7 +51,7 @@ type Config struct { TokenLogin string `mapstructure:"token_login" required:"false"` // Timeout for waiting on the API to complete // a request. Defaults to 5m. - StateTimeout config.DurationString `mapstructure:"state_timeout" required:"false"` + StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"` // ID or name of the image to launch server from. SourceImage string `mapstructure:"source_image" required:"true"` // The name of the resulting image. Defaults to @@ -145,8 +146,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.Comm.SSHUsername = defaultUserName } - if c.Comm.SSHTimeout == "" { - c.Comm.SSHTimeout = "10m" + if c.Comm.SSHTimeout == 0 { + c.Comm.SSHTimeout = 10 * time.Minute } if c.APIURL == "" { @@ -173,7 +174,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.Project = cliConfig.Profile.Project.ID } - if c.StateTimeout == "" { + if c.StateTimeout == 0 { c.StateTimeout = defaultStateTimeout } diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index c8754fc01..1b40fac84 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -270,10 +270,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &hypervcommon.StepTypeBootCommand{ BootCommand: b.config.FlatBootCommand(), - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, SwitchName: b.config.SwitchName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, }, // configure the communicator ssh, winrm @@ -293,7 +293,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &hypervcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), + Timeout: b.config.ShutdownTimeout, }, // wait for the vm to be powered off diff --git a/builder/hyperv/vmcx/builder.go b/builder/hyperv/vmcx/builder.go index 07123b072..af93007e5 100644 --- a/builder/hyperv/vmcx/builder.go +++ b/builder/hyperv/vmcx/builder.go @@ -318,10 +318,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &hypervcommon.StepTypeBootCommand{ BootCommand: b.config.FlatBootCommand(), - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, SwitchName: b.config.SwitchName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, }, // configure the communicator ssh, winrm @@ -341,7 +341,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &hypervcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), + Timeout: b.config.ShutdownTimeout, }, // wait for the vm to be powered off diff --git a/builder/linode/config.go b/builder/linode/config.go index df6346c9c..1978d0492 100644 --- a/builder/linode/config.go +++ b/builder/linode/config.go @@ -36,10 +36,9 @@ type Config struct { ImageLabel string `mapstructure:"image_label"` Description string `mapstructure:"image_description"` - RawStateTimeout string `mapstructure:"state_timeout"` + StateTimeout time.Duration `mapstructure:"state_timeout"` - stateTimeout time.Duration - interCtx interpolate.Context + interCtx interpolate.Context } func createRandomRootPassword() (string, error) { @@ -101,14 +100,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { } } - if c.RawStateTimeout == "" { - c.stateTimeout = 5 * time.Minute - } else { - if stateTimeout, err := time.ParseDuration(c.RawStateTimeout); err == nil { - c.stateTimeout = stateTimeout - } else { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Unable to parse state timeout: %s", err)) - } + if c.StateTimeout == 0 { + c.StateTimeout = 5 * time.Minute } if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { diff --git a/builder/linode/config.hcl2spec.go b/builder/linode/config.hcl2spec.go index 9fc15340e..e22bc7507 100644 --- a/builder/linode/config.hcl2spec.go +++ b/builder/linode/config.hcl2spec.go @@ -67,7 +67,6 @@ type FlatConfig struct { RootSSHKey *string `mapstructure:"root_ssh_key" cty:"root_ssh_key"` ImageLabel *string `mapstructure:"image_label" cty:"image_label"` Description *string `mapstructure:"image_description" cty:"image_description"` - RawStateTimeout *string `mapstructure:"state_timeout" cty:"state_timeout"` } // FlatMapstructure returns a new FlatConfig. @@ -137,7 +136,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "root_ssh_key": &hcldec.AttrSpec{Name: "root_ssh_key", Type: cty.String, Required: false}, "image_label": &hcldec.AttrSpec{Name: "image_label", Type: cty.String, Required: false}, "image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false}, - "state_timeout": &hcldec.AttrSpec{Name: "state_timeout", Type: cty.String, Required: false}, } return s } diff --git a/builder/lxc/config.go b/builder/lxc/config.go index d5fa44ed3..587e205a0 100644 --- a/builder/lxc/config.go +++ b/builder/lxc/config.go @@ -31,7 +31,8 @@ type Config struct { CommandWrapper string `mapstructure:"command_wrapper" required:"false"` // The timeout in seconds to wait for the the // container to start. Defaults to 20 seconds. - RawInitTimeout string `mapstructure:"init_timeout" required:"false"` + InitTimeout time.Duration `mapstructure:"init_timeout" required:"false"` + // Options to pass to lxc-create. For // instance, you can specify a custom LXC container configuration file with // ["-f", "/path/to/lxc.conf"]. Defaults to []. See man 1 lxc-create for @@ -62,7 +63,6 @@ type Config struct { // container to reach. Note some distributions (Ubuntu) simulate run levels // and may report 5 rather than 3. TargetRunlevel int `mapstructure:"target_runlevel" required:"false"` - InitTimeout time.Duration ctx interpolate.Context } @@ -98,13 +98,8 @@ func NewConfig(raws ...interface{}) (*Config, error) { c.CommandWrapper = "{{.Command}}" } - if c.RawInitTimeout == "" { - c.RawInitTimeout = "20s" - } - - c.InitTimeout, err = time.ParseDuration(c.RawInitTimeout) - if err != nil { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing init_timeout: %s", err)) + if c.InitTimeout == 0 { + c.InitTimeout = 20 * time.Second } if _, err := os.Stat(c.ConfigFile); os.IsNotExist(err) { diff --git a/builder/oracle/classic/config.go b/builder/oracle/classic/config.go index 7b56e2ecb..4fc1ddb15 100644 --- a/builder/oracle/classic/config.go +++ b/builder/oracle/classic/config.go @@ -9,6 +9,7 @@ import ( "net/url" "os" "regexp" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/communicator" @@ -31,12 +32,12 @@ type Config struct { apiEndpointURL *url.URL // Image - ImageName string `mapstructure:"image_name"` - Shape string `mapstructure:"shape"` - SourceImageList string `mapstructure:"source_image_list"` - SourceImageListEntry int `mapstructure:"source_image_list_entry"` - SnapshotTimeout config.DurationString `mapstructure:"snapshot_timeout"` - DestImageList string `mapstructure:"dest_image_list"` + ImageName string `mapstructure:"image_name"` + Shape string `mapstructure:"shape"` + SourceImageList string `mapstructure:"source_image_list"` + SourceImageListEntry int `mapstructure:"source_image_list_entry"` + SnapshotTimeout time.Duration `mapstructure:"snapshot_timeout"` + DestImageList string `mapstructure:"dest_image_list"` // Attributes and Attributes file are both optional and mutually exclusive. Attributes string `mapstructure:"attributes"` AttributesFile string `mapstructure:"attributes_file"` @@ -77,8 +78,8 @@ func NewConfig(raws ...interface{}) (*Config, error) { c.SSHSourceList = "seciplist:/oracle/public/public-internet" } - if c.SnapshotTimeout == "" { - c.SnapshotTimeout = "20m" + if c.SnapshotTimeout == 0 { + c.SnapshotTimeout = 20 * time.Minute } // Validate that all required fields are present diff --git a/builder/oracle/classic/step_snapshot.go b/builder/oracle/classic/step_snapshot.go index c5912e0c7..f11f718e0 100644 --- a/builder/oracle/classic/step_snapshot.go +++ b/builder/oracle/classic/step_snapshot.go @@ -28,7 +28,7 @@ func (s *stepSnapshot) Run(ctx context.Context, state multistep.StateBag) multis snapshotInput := &compute.CreateSnapshotInput{ Instance: fmt.Sprintf("%s/%s", config.ImageName, instanceID), MachineImage: config.ImageName, - Timeout: config.SnapshotTimeout.Duration(), + Timeout: config.SnapshotTimeout, } snap, err := snapshotClient.CreateSnapshot(snapshotInput) diff --git a/builder/parallels/common/ssh_config.go b/builder/parallels/common/ssh_config.go index df0125ce0..10fdb30cc 100644 --- a/builder/parallels/common/ssh_config.go +++ b/builder/parallels/common/ssh_config.go @@ -1,8 +1,9 @@ package common import ( + "time" + "github.com/hashicorp/packer/helper/communicator" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/template/interpolate" ) @@ -12,13 +13,13 @@ type SSHConfig struct { // These are deprecated, but we keep them around for BC // TODO(@mitchellh): remove - SSHWaitTimeout config.DurationString `mapstructure:"ssh_wait_timeout"` + SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout"` } // Prepare sets the default values for SSH communicator properties. func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error { // TODO: backwards compatibility, write fixer instead - if c.SSHWaitTimeout != "" { + if c.SSHWaitTimeout != 0 { c.Comm.SSHTimeout = c.SSHWaitTimeout } diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index b2355aef5..b7ea4788f 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -224,12 +224,12 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, ¶llelscommon.StepRun{}, ¶llelscommon.StepTypeBootCommand{ - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, BootCommand: b.config.FlatBootCommand(), HostInterfaces: b.config.HostInterfaces, VMName: b.config.VMName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, @@ -251,7 +251,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, ¶llelscommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), + Timeout: b.config.ShutdownTimeout, }, ¶llelscommon.StepPrlctl{ Commands: b.config.PrlctlPost, diff --git a/builder/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index 79e282e4b..a199650d1 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/builder.go @@ -78,11 +78,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack ¶llelscommon.StepRun{}, ¶llelscommon.StepTypeBootCommand{ BootCommand: b.config.FlatBootCommand(), - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, HostInterfaces: []string{}, VMName: b.config.VMName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, @@ -101,7 +101,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack new(common.StepProvision), ¶llelscommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), + Timeout: b.config.ShutdownTimeout, }, &common.StepCleanupTempKeys{ Comm: &b.config.SSHConfig.Comm, diff --git a/builder/proxmox/config.go b/builder/proxmox/config.go index d4deead65..b3c08ecaf 100644 --- a/builder/proxmox/config.go +++ b/builder/proxmox/config.go @@ -24,8 +24,7 @@ type Config struct { common.PackerConfig `mapstructure:",squash"` common.HTTPConfig `mapstructure:",squash"` bootcommand.BootConfig `mapstructure:",squash"` - RawBootKeyInterval string `mapstructure:"boot_key_interval"` - BootKeyInterval time.Duration `` + BootKeyInterval time.Duration `mapstructure:"boot_key_interval"` Comm communicator.Config `mapstructure:",squash"` ProxmoxURLRaw string `mapstructure:"proxmox_url"` @@ -104,18 +103,16 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { if c.Password == "" { c.Password = os.Getenv("PROXMOX_PASSWORD") } - if c.RawBootKeyInterval == "" { - c.RawBootKeyInterval = os.Getenv(common.PackerKeyEnv) - } - if c.RawBootKeyInterval == "" { - c.BootKeyInterval = 5 * time.Millisecond - } else { - if interval, err := time.ParseDuration(c.RawBootKeyInterval); err == nil { - c.BootKeyInterval = interval - } else { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Could not parse boot_key_interval: %v", err)) + if c.BootKeyInterval == 0 && os.Getenv(common.PackerKeyEnv) != "" { + var err error + c.BootKeyInterval, err = time.ParseDuration(os.Getenv(common.PackerKeyEnv)) + if err != nil { + errs = packer.MultiErrorAppend(errs, err) } } + if c.BootKeyInterval == 0 { + c.BootKeyInterval = 5 * time.Millisecond + } if c.VMName == "" { // Default to packer-[time-ordered-uuid] diff --git a/builder/proxmox/config.hcl2spec.go b/builder/proxmox/config.hcl2spec.go index abfee583c..797bf117b 100644 --- a/builder/proxmox/config.hcl2spec.go +++ b/builder/proxmox/config.hcl2spec.go @@ -22,7 +22,7 @@ type FlatConfig struct { BootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"` BootWait *string `mapstructure:"boot_wait" cty:"boot_wait"` BootCommand []string `mapstructure:"boot_command" cty:"boot_command"` - RawBootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"` + BootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"` Type *string `mapstructure:"communicator" cty:"communicator"` PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"` SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"` diff --git a/builder/proxmox/step_type_boot_command.go b/builder/proxmox/step_type_boot_command.go index 170096aa3..d40e13056 100644 --- a/builder/proxmox/step_type_boot_command.go +++ b/builder/proxmox/step_type_boot_command.go @@ -46,10 +46,10 @@ func (s *stepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) return multistep.ActionContinue } - if int64(s.BootWait.Duration()) > 0 { + if int64(s.BootWait) > 0 { ui.Say(fmt.Sprintf("Waiting %s for boot", s.BootWait)) select { - case <-time.After(s.BootWait.Duration()): + case <-time.After(s.BootWait): break case <-ctx.Done(): return multistep.ActionHalt diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index e568940f2..989e4e277 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -12,6 +12,7 @@ import ( "os/exec" "path/filepath" "runtime" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/bootcommand" @@ -319,7 +320,7 @@ type Config struct { // These are deprecated, but we keep them around for BC // TODO(@mitchellh): remove - SSHWaitTimeout config.DurationString `mapstructure:"ssh_wait_timeout" required:"false"` + SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout" required:"false"` // TODO(mitchellh): deprecate RunOnce bool `mapstructure:"run_once"` @@ -445,7 +446,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } // TODO: backwards compatibility, write fixer instead - if b.config.SSHWaitTimeout != "" { + if b.config.SSHWaitTimeout != 0 { b.config.Comm.SSHTimeout = b.config.SSHWaitTimeout } @@ -462,10 +463,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, es...) } - if err := b.config.SSHWaitTimeout.Validate(); err != nil { - errs = packer.MultiErrorAppend(errs, err) - } - if !(b.config.Format == "qcow2" || b.config.Format == "raw") { errs = packer.MultiErrorAppend( errs, errors.New("invalid format, only 'qcow2' or 'raw' are allowed")) diff --git a/builder/qemu/step_shutdown.go b/builder/qemu/step_shutdown.go index 86919cc35..b883e97e1 100644 --- a/builder/qemu/step_shutdown.go +++ b/builder/qemu/step_shutdown.go @@ -33,7 +33,7 @@ func (s *stepShutdown) Run(ctx context.Context, state multistep.StateBag) multis cancelCh := make(chan struct{}, 1) go func() { defer close(cancelCh) - <-time.After(config.ShutdownTimeout.Duration()) + <-time.After(config.ShutdownTimeout) }() ui.Say("Waiting for shutdown...") if ok := driver.WaitForShutdown(cancelCh); ok { @@ -63,7 +63,7 @@ func (s *stepShutdown) Run(ctx context.Context, state multistep.StateBag) multis cancelCh := make(chan struct{}, 1) go func() { defer close(cancelCh) - <-time.After(config.ShutdownTimeout.Duration()) + <-time.After(config.ShutdownTimeout) }() log.Printf("Waiting max %s for shutdown to complete", config.ShutdownTimeout) diff --git a/builder/qemu/step_type_boot_command.go b/builder/qemu/step_type_boot_command.go index cbeb5c7a3..c6aa09ea2 100644 --- a/builder/qemu/step_type_boot_command.go +++ b/builder/qemu/step_type_boot_command.go @@ -50,10 +50,10 @@ func (s *stepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) } // Wait the for the vm to boot. - if int64(config.BootWait.Duration()) > 0 { + if int64(config.BootWait) > 0 { ui.Say(fmt.Sprintf("Waiting %s for boot...", config.BootWait)) select { - case <-time.After(config.BootWait.Duration()): + case <-time.After(config.BootWait): break case <-ctx.Done(): return multistep.ActionHalt @@ -105,7 +105,7 @@ func (s *stepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) config.VMName, } - d := bootcommand.NewVNCDriver(c, config.VNCConfig.BootKeyInterval.Duration()) + d := bootcommand.NewVNCDriver(c, config.VNCConfig.BootKeyInterval) ui.Say("Typing the boot command over VNC...") command, err := interpolate.Render(config.VNCConfig.FlatBootCommand(), &configCtx) diff --git a/builder/vagrant/builder.go b/builder/vagrant/builder.go index e763418a0..a922ed017 100644 --- a/builder/vagrant/builder.go +++ b/builder/vagrant/builder.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/bootcommand" @@ -154,8 +155,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } - if b.config.Comm.SSHTimeout == "" { - b.config.Comm.SSHTimeout = "10m" + if b.config.Comm.SSHTimeout == 0 { + b.config.Comm.SSHTimeout = 10 * time.Minute } if b.config.Comm.Type != "ssh" { diff --git a/builder/virtualbox/common/shutdown_config.go b/builder/virtualbox/common/shutdown_config.go index 80ecae3b4..5dd70c69b 100644 --- a/builder/virtualbox/common/shutdown_config.go +++ b/builder/virtualbox/common/shutdown_config.go @@ -3,9 +3,8 @@ package common import ( - "fmt" + "time" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/template/interpolate" ) @@ -22,31 +21,18 @@ type ShutdownConfig struct { // shutdown_command for the virtual machine to actually shut down. If it // doesn't shut down in this time, it is an error. By default, the timeout is // 5m or five minutes. - ShutdownTimeout config.DurationString `mapstructure:"shutdown_timeout" required:"false"` + ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout" required:"false"` // The amount of time to wait after shutting // down the virtual machine. If you get the error // Error removing floppy controller, you might need to set this to 5m // or so. By default, the delay is 0s or disabled. - PostShutdownDelay config.DurationString `mapstructure:"post_shutdown_delay" required:"false"` + PostShutdownDelay time.Duration `mapstructure:"post_shutdown_delay" required:"false"` } func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error { - if c.ShutdownTimeout == "" { - c.ShutdownTimeout = "5m" + if c.ShutdownTimeout == 0 { + c.ShutdownTimeout = 5 * time.Minute } - if c.PostShutdownDelay == "" { - c.PostShutdownDelay = "0s" - } - - var errs []error - if err := c.ShutdownTimeout.Validate(); err != nil { - errs = append(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) - } - - if err := c.PostShutdownDelay.Validate(); err != nil { - errs = append(errs, fmt.Errorf("Failed parsing post_shutdown_delay: %s", err)) - } - - return errs + return nil } diff --git a/builder/virtualbox/common/shutdown_config_test.go b/builder/virtualbox/common/shutdown_config_test.go index 1a67f69ba..206e2f848 100644 --- a/builder/virtualbox/common/shutdown_config_test.go +++ b/builder/virtualbox/common/shutdown_config_test.go @@ -26,22 +26,14 @@ func TestShutdownConfigPrepare_ShutdownTimeout(t *testing.T) { var c *ShutdownConfig var errs []error - // Test with a bad value - c = testShutdownConfig() - c.ShutdownTimeout = "this is not good" - errs = c.Prepare(interpolate.NewContext()) - if len(errs) == 0 { - t.Fatalf("should have error") - } - // Test with a good one c = testShutdownConfig() - c.ShutdownTimeout = "5s" + c.ShutdownTimeout = 5 * time.Second errs = c.Prepare(interpolate.NewContext()) if len(errs) > 0 { t.Fatalf("err: %#v", errs) } - if c.ShutdownTimeout.Duration() != 5*time.Second { + if c.ShutdownTimeout != 5*time.Second { t.Fatalf("bad: %s", c.ShutdownTimeout) } } @@ -50,33 +42,25 @@ func TestShutdownConfigPrepare_PostShutdownDelay(t *testing.T) { var c *ShutdownConfig var errs []error - // Test with a bad value - c = testShutdownConfig() - c.PostShutdownDelay = "this is not good" - errs = c.Prepare(interpolate.NewContext()) - if len(errs) == 0 { - t.Fatalf("should have error") - } - // Test with default value c = testShutdownConfig() - c.PostShutdownDelay = "" + c.PostShutdownDelay = 0 errs = c.Prepare(interpolate.NewContext()) if len(errs) > 0 { t.Fatalf("err: %#v", errs) } - if c.PostShutdownDelay.Duration().Nanoseconds() != 0 { + if c.PostShutdownDelay.Nanoseconds() != 0 { t.Fatalf("bad: %s", c.PostShutdownDelay) } // Test with a good one c = testShutdownConfig() - c.PostShutdownDelay = "5s" + c.PostShutdownDelay = 5 * time.Millisecond errs = c.Prepare(interpolate.NewContext()) if len(errs) > 0 { t.Fatalf("err: %#v", errs) } - if c.PostShutdownDelay.Duration() != 5*time.Second { + if c.PostShutdownDelay != 5*time.Millisecond { t.Fatalf("bad: %s", c.PostShutdownDelay) } } diff --git a/builder/virtualbox/common/ssh_config.go b/builder/virtualbox/common/ssh_config.go index 12d7284c4..074415535 100644 --- a/builder/virtualbox/common/ssh_config.go +++ b/builder/virtualbox/common/ssh_config.go @@ -4,9 +4,9 @@ package common import ( "errors" + "time" "github.com/hashicorp/packer/helper/communicator" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/template/interpolate" ) @@ -26,7 +26,7 @@ type SSHConfig struct { // These are deprecated, but we keep them around for BC // TODO(@mitchellh): remove - SSHWaitTimeout config.DurationString `mapstructure:"ssh_wait_timeout"` + SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout"` } func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error { @@ -43,7 +43,7 @@ func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error { } // TODO: backwards compatibility, write fixer instead - if c.SSHWaitTimeout != "" { + if c.SSHWaitTimeout != 0 { c.Comm.SSHTimeout = c.SSHWaitTimeout } diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 36a5eaca0..5ff62c54e 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -319,11 +319,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Headless: b.config.Headless, }, &vboxcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, Comm: &b.config.Comm, }, &communicator.StepConnect{ @@ -347,8 +347,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &vboxcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), - Delay: b.config.PostShutdownDelay.Duration(), + Timeout: b.config.ShutdownTimeout, + Delay: b.config.PostShutdownDelay, }, &vboxcommon.StepRemoveDevices{ Bundling: b.config.VBoxBundleConfig, diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index 7abf36b64..260a4ce64 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -112,11 +112,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Headless: b.config.Headless, }, &vboxcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, Comm: &b.config.Comm, }, &communicator.StepConnect{ @@ -140,8 +140,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &vboxcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), - Delay: b.config.PostShutdownDelay.Duration(), + Timeout: b.config.ShutdownTimeout, + Delay: b.config.PostShutdownDelay, }, &vboxcommon.StepRemoveDevices{ GuestAdditionsInterface: b.config.GuestAdditionsInterface, diff --git a/builder/virtualbox/vm/builder.go b/builder/virtualbox/vm/builder.go index c76535954..25f825622 100644 --- a/builder/virtualbox/vm/builder.go +++ b/builder/virtualbox/vm/builder.go @@ -96,11 +96,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Headless: b.config.Headless, }, &vboxcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, - GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(), + GroupInterval: b.config.BootConfig.BootGroupInterval, Comm: &b.config.Comm, }, &communicator.StepConnect{ @@ -124,8 +124,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &vboxcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), - Delay: b.config.PostShutdownDelay.Duration(), + Timeout: b.config.ShutdownTimeout, + Delay: b.config.PostShutdownDelay, }, &vboxcommon.StepVBoxManage{ Commands: b.config.VBoxManagePost, diff --git a/builder/virtualbox/vm/config.go b/builder/virtualbox/vm/config.go index 24ad2535b..14b57295d 100644 --- a/builder/virtualbox/vm/config.go +++ b/builder/virtualbox/vm/config.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "strings" + "time" vboxcommon "github.com/hashicorp/packer/builder/virtualbox/common" "github.com/hashicorp/packer/common" @@ -71,8 +72,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.GuestAdditionsPath = "VBoxGuestAdditions.iso" } - if c.PostShutdownDelay == "" { - c.PostShutdownDelay = "2s" + if c.PostShutdownDelay == 0 { + c.PostShutdownDelay = 2 * time.Second } // Prepare the errors diff --git a/builder/vmware/common/ssh_config.go b/builder/vmware/common/ssh_config.go index c93344e77..8c59cdedc 100644 --- a/builder/vmware/common/ssh_config.go +++ b/builder/vmware/common/ssh_config.go @@ -3,8 +3,9 @@ package common import ( + "time" + "github.com/hashicorp/packer/helper/communicator" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/template/interpolate" ) @@ -16,12 +17,12 @@ type SSHConfig struct { SSHSkipRequestPty bool `mapstructure:"ssh_skip_request_pty"` // These are deprecated, but we keep them around for BC // TODO(@mitchellh): remove - SSHWaitTimeout config.DurationString `mapstructure:"ssh_wait_timeout"` + SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout"` } func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error { // TODO: backwards compatibility, write fixer instead - if c.SSHWaitTimeout != "" { + if c.SSHWaitTimeout != 0 { c.Comm.SSHTimeout = c.SSHWaitTimeout } if c.SSHSkipRequestPty { diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 81e56818d..7e94d9663 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -131,12 +131,12 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Headless: b.config.Headless, }, &vmwcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, VNCEnabled: !b.config.DisableVNC, BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, - KeyInterval: b.config.VNCConfig.BootKeyInterval.Duration(), + KeyInterval: b.config.VNCConfig.BootKeyInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, @@ -155,7 +155,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &vmwcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), + Timeout: b.config.ShutdownTimeout, }, &vmwcommon.StepCleanFiles{}, &vmwcommon.StepCompactDisk{ diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 03a201828..e1e33dd7c 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -128,12 +128,12 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Headless: b.config.Headless, }, &vmwcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait.Duration(), + BootWait: b.config.BootWait, VNCEnabled: !b.config.DisableVNC, BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, - KeyInterval: b.config.VNCConfig.BootKeyInterval.Duration(), + KeyInterval: b.config.VNCConfig.BootKeyInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, @@ -152,7 +152,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &vmwcommon.StepShutdown{ Command: b.config.ShutdownCommand, - Timeout: b.config.ShutdownTimeout.Duration(), + Timeout: b.config.ShutdownTimeout, }, &vmwcommon.StepCleanFiles{}, &vmwcommon.StepCompactDisk{ diff --git a/builder/yandex/config.go b/builder/yandex/config.go index 248b1ffe0..2319203e1 100644 --- a/builder/yandex/config.go +++ b/builder/yandex/config.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "regexp" + "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/uuid" @@ -118,7 +119,7 @@ type Config struct { ctx interpolate.Context // The time to wait for instance state changes. // Defaults to `5m`. - StateTimeout config.DurationString `mapstructure:"state_timeout" required:"false"` + StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"` } func NewConfig(raws ...interface{}) (*Config, []string, error) { @@ -279,12 +280,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { } } - if c.StateTimeout == "" { - c.StateTimeout = "5m" - } - - if err := c.StateTimeout.Validate(); err != nil { - errs = packer.MultiErrorAppend(errs, err) + if c.StateTimeout == 0 { + c.StateTimeout = 5 * time.Minute } // Check for any errors. diff --git a/builder/yandex/step_create_image.go b/builder/yandex/step_create_image.go index 08842906c..4e40f188c 100644 --- a/builder/yandex/step_create_image.go +++ b/builder/yandex/step_create_image.go @@ -22,7 +22,7 @@ func (stepCreateImage) Run(ctx context.Context, state multistep.StateBag) multis diskID := state.Get("disk_id").(string) ui.Say(fmt.Sprintf("Creating image: %v", c.ImageName)) - ctx, cancel := context.WithTimeout(ctx, c.StateTimeout.Duration()) + ctx, cancel := context.WithTimeout(ctx, c.StateTimeout) defer cancel() op, err := sdk.WrapOperation(sdk.Compute().Image().Create(ctx, &compute.CreateImageRequest{ diff --git a/builder/yandex/step_create_instance.go b/builder/yandex/step_create_instance.go index 5e7341cad..5d7b28f10 100644 --- a/builder/yandex/step_create_instance.go +++ b/builder/yandex/step_create_instance.go @@ -112,7 +112,7 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) - ctx, cancel := context.WithTimeout(ctx, config.StateTimeout.Duration()) + ctx, cancel := context.WithTimeout(ctx, config.StateTimeout) defer cancel() sourceImage, err := getImage(ctx, config, driver) @@ -263,7 +263,7 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) - ctx, cancel := context.WithTimeout(context.Background(), config.StateTimeout.Duration()) + ctx, cancel := context.WithTimeout(context.Background(), config.StateTimeout) defer cancel() if s.SerialLogFile != "" { diff --git a/builder/yandex/step_instance_info.go b/builder/yandex/step_instance_info.go index a194e5ae5..fa85c052d 100644 --- a/builder/yandex/step_instance_info.go +++ b/builder/yandex/step_instance_info.go @@ -22,7 +22,7 @@ func (s *stepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) mu ui.Say(fmt.Sprintf("Waiting for instance with id %s to become active...", instanceID)) - ctx, cancel := context.WithTimeout(ctx, c.StateTimeout.Duration()) + ctx, cancel := context.WithTimeout(ctx, c.StateTimeout) defer cancel() instance, err := sdk.Compute().Instance().Get(ctx, &compute.GetInstanceRequest{ diff --git a/builder/yandex/step_teardown_instance.go b/builder/yandex/step_teardown_instance.go index 0af11c29a..ee3d0dbd3 100644 --- a/builder/yandex/step_teardown_instance.go +++ b/builder/yandex/step_teardown_instance.go @@ -21,7 +21,7 @@ func (s *stepTeardownInstance) Run(ctx context.Context, state multistep.StateBag instanceID := state.Get("instance_id").(string) ui.Say("Stopping instance...") - ctx, cancel := context.WithTimeout(ctx, c.StateTimeout.Duration()) + ctx, cancel := context.WithTimeout(ctx, c.StateTimeout) defer cancel() op, err := sdk.WrapOperation(sdk.Compute().Instance().Stop(ctx, &compute.StopInstanceRequest{ InstanceId: instanceID, diff --git a/cmd/mapstructure-to-hcl2/mapstructure-to-hcl2.go b/cmd/mapstructure-to-hcl2/mapstructure-to-hcl2.go index eb8d35a76..da3a507bf 100644 --- a/cmd/mapstructure-to-hcl2/mapstructure-to-hcl2.go +++ b/cmd/mapstructure-to-hcl2/mapstructure-to-hcl2.go @@ -431,7 +431,7 @@ func getMapstructureSquashedStruct(topPkg *types.Package, utStruct *types.Struct switch f := field.Type().(type) { case *types.Named: switch f.String() { - case "time.Duration", "github.com/hashicorp/packer/helper/config.DurationString": + case "time.Duration": field = types.NewField(field.Pos(), field.Pkg(), field.Name(), types.NewPointer(types.Typ[types.String]), field.Embedded()) case "github.com/hashicorp/packer/helper/config.Trilean": // TODO(azr): unhack this situation field = types.NewField(field.Pos(), field.Pkg(), field.Name(), types.NewPointer(types.Typ[types.Bool]), field.Embedded()) diff --git a/cmd/struct-markdown/main.go b/cmd/struct-markdown/main.go index 487704bef..9d0bf3a5b 100644 --- a/cmd/struct-markdown/main.go +++ b/cmd/struct-markdown/main.go @@ -112,8 +112,8 @@ func main() { fieldType := string(b[field.Type.Pos()-1 : field.Type.End()-1]) fieldType = strings.ReplaceAll(fieldType, "*", `\*`) switch fieldType { - case "config.DurationString": - fieldType = "duration string. ex: \"1h5m2s\"" + case "time.Duration": + fieldType = `duration string | ex: "1h5m2s"` } field := Field{ diff --git a/common/bootcommand/config.go b/common/bootcommand/config.go index d32798c1f..607ee6f9e 100644 --- a/common/bootcommand/config.go +++ b/common/bootcommand/config.go @@ -5,8 +5,8 @@ package bootcommand import ( "fmt" "strings" + "time" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/template/interpolate" ) @@ -112,13 +112,13 @@ type BootConfig struct { // Packer to wait five seconds and one minute 30 seconds, respectively. If // this isn't specified, a sensible default value is picked depending on // the builder type. - BootGroupInterval config.DurationString `mapstructure:"boot_keygroup_interval"` + BootGroupInterval time.Duration `mapstructure:"boot_keygroup_interval"` // The time to wait after booting the initial virtual machine before typing // the `boot_command`. The value of this should be a duration. Examples are // `5s` and `1m30s` which will cause Packer to wait five seconds and one // minute 30 seconds, respectively. If this isn't specified, the default is // `10s` or 10 seconds. - BootWait config.DurationString `mapstructure:"boot_wait"` + BootWait time.Duration `mapstructure:"boot_wait"` // This is an array of commands to type when the virtual machine is first // booted. The goal of these commands should be to type just enough to // initialize the operating system installer. Special keys can be typed as @@ -140,26 +140,12 @@ type VNCConfig struct { // when this is true. Defaults to false. DisableVNC bool `mapstructure:"disable_vnc"` // Time in ms to wait between each key press - BootKeyInterval config.DurationString `mapstructure:"boot_key_interval"` + BootKeyInterval time.Duration `mapstructure:"boot_key_interval"` } func (c *BootConfig) Prepare(ctx *interpolate.Context) (errs []error) { - if c.BootWait == "" { - c.BootWait = "10s" - } - - if err := c.BootWait.Validate(); err != nil { - errs = append( - errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) - } - - if c.BootGroupInterval == "" { - c.BootGroupInterval = "0ms" - } - - if err := c.BootGroupInterval.Validate(); err != nil { - errs = append( - errs, fmt.Errorf("Failed parsing boot_keygroup_interval: %s", err)) + if c.BootWait == 0 { + c.BootWait = 10 * time.Second } if c.BootCommand != nil { @@ -184,15 +170,6 @@ func (c *VNCConfig) Prepare(ctx *interpolate.Context) (errs []error) { fmt.Errorf("A boot command cannot be used when vnc is disabled.")) } - if c.BootKeyInterval == "" { - c.BootKeyInterval = "0ms" - } - - if err := c.BootKeyInterval.Validate(); err != nil { - errs = append( - errs, fmt.Errorf("Failed parsing boot_key_interval: %s", err)) - } - errs = append(errs, c.BootConfig.Prepare(ctx)...) return } diff --git a/common/bootcommand/config_test.go b/common/bootcommand/config_test.go index 9254a108e..0f56e1c15 100644 --- a/common/bootcommand/config_test.go +++ b/common/bootcommand/config_test.go @@ -2,6 +2,7 @@ package bootcommand import ( "testing" + "time" "github.com/hashicorp/packer/template/interpolate" ) @@ -11,26 +12,18 @@ func TestConfigPrepare(t *testing.T) { // Test a default boot_wait c = new(BootConfig) - c.BootWait = "" + c.BootWait = 0 errs := c.Prepare(&interpolate.Context{}) if len(errs) > 0 { t.Fatalf("bad: %#v", errs) } - if c.BootWait != "10s" { + if c.BootWait != 10*time.Second { t.Fatalf("bad value: %s", c.BootWait) } - // Test with a bad boot_wait - c = new(BootConfig) - c.BootWait = "this is not good" - errs = c.Prepare(&interpolate.Context{}) - if len(errs) == 0 { - t.Fatal("should error") - } - // Test with a good one c = new(BootConfig) - c.BootWait = "5s" + c.BootWait = 5 * time.Second errs = c.Prepare(&interpolate.Context{}) if len(errs) > 0 { t.Fatalf("bad: %#v", errs) diff --git a/common/shutdowncommand/config.go b/common/shutdowncommand/config.go index 36ce8bb5e..efea7db8d 100644 --- a/common/shutdowncommand/config.go +++ b/common/shutdowncommand/config.go @@ -3,7 +3,8 @@ package shutdowncommand import ( - "github.com/hashicorp/packer/helper/config" + "time" + "github.com/hashicorp/packer/template/interpolate" ) @@ -21,16 +22,12 @@ type ShutdownConfig struct { // virtual machine to actually shut down. If the machine doesn't shut down // in this time it is considered an error. By default, the time out is "5m" // (five minutes). - ShutdownTimeout config.DurationString `mapstructure:"shutdown_timeout" required:"false"` + ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout" required:"false"` } func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error { - if c.ShutdownTimeout == "" { - c.ShutdownTimeout = "5m" - } - - if err := c.ShutdownTimeout.Validate(); err != nil { - return []error{err} + if c.ShutdownTimeout == 0 { + c.ShutdownTimeout = 5 * time.Minute } return nil diff --git a/common/shutdowncommand/config_test.go b/common/shutdowncommand/config_test.go index 3f63f599c..ada363a2f 100644 --- a/common/shutdowncommand/config_test.go +++ b/common/shutdowncommand/config_test.go @@ -26,22 +26,14 @@ func TestShutdownConfigPrepare_ShutdownTimeout(t *testing.T) { var c *ShutdownConfig var errs []error - // Test with a bad value - c = testShutdownConfig() - c.ShutdownTimeout = "this is not good" - errs = c.Prepare(interpolate.NewContext()) - if len(errs) == 0 { - t.Fatalf("should have error") - } - // Test with a good one c = testShutdownConfig() - c.ShutdownTimeout = "5s" + c.ShutdownTimeout = 5 * time.Second errs = c.Prepare(interpolate.NewContext()) if len(errs) > 0 { t.Fatalf("err: %#v", errs) } - if c.ShutdownTimeout.Duration() != 5*time.Second { + if c.ShutdownTimeout != 5*time.Second { t.Fatalf("bad: %s", c.ShutdownTimeout) } } diff --git a/helper/communicator/config.go b/helper/communicator/config.go index ced93494e..c6c5d880e 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -9,9 +9,9 @@ import ( "io/ioutil" "net" "os" + "time" packerssh "github.com/hashicorp/packer/communicator/ssh" - "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/multistep" helperssh "github.com/hashicorp/packer/helper/ssh" "github.com/hashicorp/packer/packer" @@ -58,7 +58,7 @@ type Config struct { // In this example, Packer will check whether it can connect, as normal. But once // a connection attempt is successful, it will disconnect and then wait 10 minutes // before connecting to the guest and beginning provisioning. - PauseBeforeConnect config.DurationString `mapstructure:"pause_before_connecting"` + PauseBeforeConnect time.Duration `mapstructure:"pause_before_connecting"` SSH `mapstructure:",squash"` WinRM `mapstructure:",squash"` @@ -104,7 +104,7 @@ type SSH struct { // The time to wait for SSH to become available. Packer uses this to // determine when the machine has booted so this is usually quite long. // Example value: `10m`. - SSHTimeout config.DurationString `mapstructure:"ssh_timeout"` + SSHTimeout time.Duration `mapstructure:"ssh_timeout"` // If true, the local SSH agent will be used to authenticate connections to // the source instance. No temporary keypair will be created, and the // values of `ssh_password` and `ssh_private_key_file` will be ignored. To @@ -146,11 +146,11 @@ type SSH struct { SSHProxyPassword string `mapstructure:"ssh_proxy_password"` // How often to send "keep alive" messages to the server. Set to a negative // value (`-1s`) to disable. Example value: `10s`. Defaults to `5s`. - SSHKeepAliveInterval config.DurationString `mapstructure:"ssh_keep_alive_interval"` + SSHKeepAliveInterval time.Duration `mapstructure:"ssh_keep_alive_interval"` // The amount of time to wait for a remote command to end. This might be // useful if, for example, packer hangs on a connection after a reboot. // Example: `5m`. Disabled by default. - SSHReadWriteTimeout config.DurationString `mapstructure:"ssh_read_write_timeout"` + SSHReadWriteTimeout time.Duration `mapstructure:"ssh_read_write_timeout"` // Tunneling @@ -201,7 +201,7 @@ type WinRM struct { WinRMPort int `mapstructure:"winrm_port"` // The amount of time to wait for WinRM to become available. This defaults // to `30m` since setting up a Windows machine generally takes a long time. - WinRMTimeout config.DurationString `mapstructure:"winrm_timeout"` + WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` // If `true`, use HTTPS for WinRM. WinRMUseSSL bool `mapstructure:"winrm_use_ssl"` // If `true`, do not check server certificate chain and host name. @@ -370,12 +370,12 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error { c.SSHPort = 22 } - if c.SSHTimeout == "" { - c.SSHTimeout = "5m" + if c.SSHTimeout == 0 { + c.SSHTimeout = 5 * time.Minute } - if c.SSHKeepAliveInterval == "" { - c.SSHKeepAliveInterval = "5s" + if c.SSHKeepAliveInterval == 0 { + c.SSHKeepAliveInterval = 5 * time.Second } if c.SSHHandshakeAttempts == 0 { @@ -404,13 +404,6 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error { // Validation var errs []error - - for _, d := range []config.DurationString{c.SSHTimeout, c.SSHKeepAliveInterval} { - if err := d.Validate(); err != nil { - errs = append(errs, err) - } - } - if c.SSHUsername == "" { errs = append(errs, errors.New("An ssh_username must be specified\n Note: some builders used to default ssh_username to \"root\".")) } @@ -484,12 +477,8 @@ func (c *Config) prepareWinRM(ctx *interpolate.Context) (errs []error) { c.WinRMPort = 5985 } - if c.WinRMTimeout == "" { - c.WinRMTimeout = "30m" - } - - if err := c.WinRMTimeout.Validate(); err != nil { - errs = append(errs, err) + if c.WinRMTimeout == 0 { + c.WinRMTimeout = 30 * time.Minute } if c.WinRMUseNTLM == true { diff --git a/helper/communicator/step_connect.go b/helper/communicator/step_connect.go index 6a05a030d..6bb062f80 100644 --- a/helper/communicator/step_connect.go +++ b/helper/communicator/step_connect.go @@ -112,8 +112,8 @@ func (s *StepConnect) Run(ctx context.Context, state multistep.StateBag) multist return action } - if s.Config.PauseBeforeConnect.Duration() > 0 { - cancelled := s.pause(s.Config.PauseBeforeConnect.Duration(), ctx) + if s.Config.PauseBeforeConnect > 0 { + cancelled := s.pause(s.Config.PauseBeforeConnect, ctx) if cancelled { return multistep.ActionHalt } diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index a816f6c13..07763e335 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -46,7 +46,7 @@ func (s *StepConnectSSH) Run(ctx context.Context, state multistep.StateBag) mult }() log.Printf("[INFO] Waiting for SSH, up to timeout: %s", s.Config.SSHTimeout) - timeout := time.After(s.Config.SSHTimeout.Duration()) + timeout := time.After(s.Config.SSHTimeout) for { // Wait for either SSH to become available, a timeout to occur, // or an interrupt to come through. @@ -198,8 +198,8 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, ctx context.Contex Pty: s.Config.SSHPty, DisableAgentForwarding: s.Config.SSHDisableAgentForwarding, UseSftp: s.Config.SSHFileTransferMethod == "sftp", - KeepAliveInterval: s.Config.SSHKeepAliveInterval.Duration(), - Timeout: s.Config.SSHReadWriteTimeout.Duration(), + KeepAliveInterval: s.Config.SSHKeepAliveInterval, + Timeout: s.Config.SSHReadWriteTimeout, Tunnels: tunnels, } diff --git a/helper/communicator/step_connect_winrm.go b/helper/communicator/step_connect_winrm.go index 62ddaa13a..275468bc1 100644 --- a/helper/communicator/step_connect_winrm.go +++ b/helper/communicator/step_connect_winrm.go @@ -49,7 +49,7 @@ func (s *StepConnectWinRM) Run(ctx context.Context, state multistep.StateBag) mu }() log.Printf("Waiting for WinRM, up to timeout: %s", s.Config.WinRMTimeout) - timeout := time.After(s.Config.WinRMTimeout.Duration()) + timeout := time.After(s.Config.WinRMTimeout) for { // Wait for either WinRM to become available, a timeout to occur, // or an interrupt to come through. @@ -136,7 +136,7 @@ func (s *StepConnectWinRM) waitForWinRM(state multistep.StateBag, ctx context.Co Port: port, Username: user, Password: password, - Timeout: s.Config.WinRMTimeout.Duration(), + Timeout: s.Config.WinRMTimeout, Https: s.Config.WinRMUseSSL, Insecure: s.Config.WinRMInsecure, TransportDecorator: s.Config.WinRMTransportDecorator, diff --git a/helper/config/decode.go b/helper/config/decode.go index 3b7d10c45..43673e1dc 100644 --- a/helper/config/decode.go +++ b/helper/config/decode.go @@ -31,6 +31,7 @@ var DefaultDecodeHookFuncs = []mapstructure.DecodeHookFunc{ uint8ToStringHook, stringToTrilean, mapstructure.StringToSliceHookFunc(","), + mapstructure.StringToTimeDurationHookFunc(), } // Decode decodes the configuration into the target and optionally diff --git a/helper/config/decode_test.go b/helper/config/decode_test.go index dd34f0bb4..b08fb2af1 100644 --- a/helper/config/decode_test.go +++ b/helper/config/decode_test.go @@ -3,6 +3,7 @@ package config import ( "reflect" "testing" + "time" "github.com/hashicorp/packer/template/interpolate" ) @@ -11,7 +12,7 @@ func TestDecode(t *testing.T) { type Target struct { Name string Address string - Time DurationString + Time time.Duration Trilean Trilean } @@ -30,7 +31,7 @@ func TestDecode(t *testing.T) { }, &Target{ Name: "bar", - Time: "5s", + Time: 5 * time.Second, Trilean: TriTrue, }, nil, diff --git a/helper/config/duration.go b/helper/config/duration.go deleted file mode 100644 index c9b939ff6..000000000 --- a/helper/config/duration.go +++ /dev/null @@ -1,36 +0,0 @@ -package config - -import ( - "fmt" - "time" -) - -// DurationString is a string that represents a time duration. -// -// A DurationString is validated using time.ParseDuration. -// -// An empty string ("") is a valid (0) DurationString. A time.Sleep(0) returns -// immediately. -type DurationString string - -// Duration returns the parsed duration. -// Duration panics if d is invalid. -func (d DurationString) Duration() time.Duration { - if d == "" { - return 0 - } - du, err := time.ParseDuration(string(d)) - if err != nil { - s := fmt.Sprintf("DurationString: Could not parse '%s' : %v", d, err) - panic(s) - } - return du -} - -func (d DurationString) Validate() error { - if d == "" { - return nil - } - _, err := time.ParseDuration(string(d)) - return err -} diff --git a/packer/core.go b/packer/core.go index d00713e48..cae4c39cc 100644 --- a/packer/core.go +++ b/packer/core.go @@ -135,14 +135,14 @@ func (c *Core) generateCoreBuildProvisioner(rawP *template.Provisioner, rawName } } // If we're pausing, we wrap the provisioner in a special pauser. - if rawP.PauseBefore != "" { + if rawP.PauseBefore != 0 { provisioner = &PausedProvisioner{ - PauseBefore: rawP.PauseBefore.Duration(), + PauseBefore: rawP.PauseBefore, Provisioner: provisioner, } - } else if rawP.Timeout != "" { + } else if rawP.Timeout != 0 { provisioner = &TimeoutProvisioner{ - Timeout: rawP.Timeout.Duration(), + Timeout: rawP.Timeout, Provisioner: provisioner, } } diff --git a/post-processor/digitalocean-import/post-processor.go b/post-processor/digitalocean-import/post-processor.go index 43eb77343..57e82f668 100644 --- a/post-processor/digitalocean-import/post-processor.go +++ b/post-processor/digitalocean-import/post-processor.go @@ -45,7 +45,7 @@ type Config struct { Distribution string `mapstructure:"image_distribution"` ImageRegions []string `mapstructure:"image_regions"` - Timeout config.DurationString `mapstructure:"timeout"` + Timeout time.Duration `mapstructure:"timeout"` ctx interpolate.Context } @@ -104,8 +104,8 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { p.config.Distribution = "Unkown" } - if p.config.Timeout == "" { - p.config.Timeout = "20m" + if p.config.Timeout == 0 { + p.config.Timeout = 20 * time.Minute } errs := new(packer.MultiError) @@ -208,7 +208,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact } ui.Message(fmt.Sprintf("Waiting for import of image %s to complete (may take a while)", p.config.Name)) - err = waitUntilImageAvailable(client, image.ID, p.config.Timeout.Duration()) + err = waitUntilImageAvailable(client, image.ID, p.config.Timeout) if err != nil { return nil, false, false, fmt.Errorf("Import of image %s failed with error: %s", p.config.Name, err) } @@ -222,7 +222,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact regions = regions[:len(regions)-1] ui.Message(fmt.Sprintf("Distributing image %s to additional regions: %v", p.config.Name, regions)) - err = distributeImageToRegions(client, image.ID, regions, p.config.Timeout.Duration()) + err = distributeImageToRegions(client, image.ID, regions, p.config.Timeout) if err != nil { return nil, false, false, err } diff --git a/post-processor/googlecompute-export/post-processor.go b/post-processor/googlecompute-export/post-processor.go index 4bfdd0817..6183619a3 100644 --- a/post-processor/googlecompute-export/post-processor.go +++ b/post-processor/googlecompute-export/post-processor.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "strings" + "time" "github.com/hashicorp/packer/builder/googlecompute" "github.com/hashicorp/packer/common" @@ -138,7 +139,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact Metadata: exporterMetadata, Network: p.config.Network, NetworkProjectId: builderProjectId, - StateTimeout: "5m", + StateTimeout: 5 * time.Minute, SourceImageFamily: "debian-9-worker", SourceImageProjectId: "compute-image-tools", Subnetwork: p.config.Subnetwork, diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 5c8d028e8..e541a782b 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -53,7 +53,7 @@ type Config struct { // The timeout for retrying to start the process. Until this timeout is // reached, if the provisioner can't start a process, it retries. This // can be set high to allow for reboots. - StartRetryTimeout config.DurationString `mapstructure:"start_retry_timeout"` + StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"` // This is used in the template generation to format environment variables // inside the `ExecuteCommand` template. @@ -143,8 +143,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.Inline = nil } - if p.config.StartRetryTimeout == "" { - p.config.StartRetryTimeout = "5m" + if p.config.StartRetryTimeout == 0 { + p.config.StartRetryTimeout = 5 * time.Minute } if p.config.RemotePath == "" { @@ -279,7 +279,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C // that the upload succeeded, a restart is initiated, and then the // command is executed but the file doesn't exist any longer. var cmd *packer.RemoteCmd - err = retry.Config{StartTimeout: p.config.StartRetryTimeout.Duration()}.Run(ctx, func(ctx context.Context) error { + err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error { if _, err := f.Seek(0, 0); err != nil { return err } @@ -391,7 +391,7 @@ func (p *Provisioner) uploadEnvVars(flattenedEnvVars string) (err error) { // a system restart envVarReader := strings.NewReader(flattenedEnvVars) log.Printf("Uploading env vars to %s", p.config.RemoteEnvVarPath) - err = retry.Config{StartTimeout: p.config.StartRetryTimeout.Duration()}.Run(ctx, func(context.Context) error { + err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(context.Context) error { if err := p.communicator.Upload(p.config.RemoteEnvVarPath, envVarReader, nil); err != nil { return fmt.Errorf("Error uploading ps script containing env vars: %s", err) } diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index e43a3ccc1..cef4611d1 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -8,6 +8,7 @@ import ( "regexp" "strings" "testing" + "time" "github.com/hashicorp/packer/packer" ) @@ -509,7 +510,7 @@ func TestProvisionerProvision_UploadFails(t *testing.T) { p := new(Provisioner) comm := new(packer.ScriptUploadErrorMockCommunicator) p.Prepare(config) - p.config.StartRetryTimeout = "1s" + p.config.StartRetryTimeout = 1 * time.Second err := p.Provision(context.Background(), ui, comm) if !strings.Contains(err.Error(), packer.ScriptUploadErrorMockCommunicatorError.Error()) { t.Fatalf("expected Provision() error %q to contain %q", diff --git a/provisioner/shell/provisioner.go b/provisioner/shell/provisioner.go index 3181c63ae..685b514ec 100644 --- a/provisioner/shell/provisioner.go +++ b/provisioner/shell/provisioner.go @@ -33,9 +33,7 @@ type Config struct { InlineShebang string `mapstructure:"inline_shebang"` // A duration of how long to pause after the provisioner - RawPauseAfter string `mapstructure:"pause_after"` - - PauseAfter time.Duration + PauseAfter time.Duration `mapstructure:"pause_after"` // Write the Vars to a file and source them from there rather than declaring // inline @@ -52,15 +50,14 @@ type Config struct { // The timeout for retrying to start the process. Until this timeout // is reached, if the provisioner can't start a process, it retries. // This can be set high to allow for reboots. - RawStartRetryTimeout string `mapstructure:"start_retry_timeout"` + StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"` // Whether to clean scripts up SkipClean bool `mapstructure:"skip_clean"` ExpectDisconnect bool `mapstructure:"expect_disconnect"` - startRetryTimeout time.Duration - ctx interpolate.Context + ctx interpolate.Context // name of the tmp environment variable file, if UseEnvVarFile is true envVarFile string } @@ -104,8 +101,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.InlineShebang = "/bin/sh -e" } - if p.config.RawStartRetryTimeout == "" { - p.config.RawStartRetryTimeout = "5m" + if p.config.StartRetryTimeout == 0 { + p.config.StartRetryTimeout = 5 * time.Minute } if p.config.RemoteFolder == "" { @@ -163,22 +160,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } } - if p.config.RawStartRetryTimeout != "" { - p.config.startRetryTimeout, err = time.ParseDuration(p.config.RawStartRetryTimeout) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Failed parsing start_retry_timeout: %s", err)) - } - } - - if p.config.RawPauseAfter != "" { - p.config.PauseAfter, err = time.ParseDuration(p.config.RawPauseAfter) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Failed parsing pause_after: %s", err)) - } - } - if errs != nil && len(errs.Errors) > 0 { return errs } @@ -240,7 +221,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C // upload the var file var cmd *packer.RemoteCmd - err = retry.Config{StartTimeout: p.config.startRetryTimeout}.Run(ctx, func(ctx context.Context) error { + err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error { if _, err := tf.Seek(0, 0); err != nil { return err } @@ -303,7 +284,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C // and then the command is executed but the file doesn't exist // any longer. var cmd *packer.RemoteCmd - err = retry.Config{StartTimeout: p.config.startRetryTimeout}.Run(ctx, func(ctx context.Context) error { + err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error { if _, err := f.Seek(0, 0); err != nil { return err } @@ -365,7 +346,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C } } - if p.config.RawPauseAfter != "" { + if p.config.PauseAfter != 0 { ui.Say(fmt.Sprintf("Pausing %s after this provisioner...", p.config.PauseAfter)) select { case <-time.After(p.config.PauseAfter): @@ -378,7 +359,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C func (p *Provisioner) cleanupRemoteFile(path string, comm packer.Communicator) error { ctx := context.TODO() - err := retry.Config{StartTimeout: p.config.startRetryTimeout}.Run(ctx, func(ctx context.Context) error { + err := retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error { cmd := &packer.RemoteCmd{ Command: fmt.Sprintf("rm -f %s", path), } diff --git a/provisioner/shell/provisioner.hcl2spec.go b/provisioner/shell/provisioner.hcl2spec.go index f07abce86..9f1fbc75c 100644 --- a/provisioner/shell/provisioner.hcl2spec.go +++ b/provisioner/shell/provisioner.hcl2spec.go @@ -9,29 +9,29 @@ import ( // FlatConfig is an auto-generated flat version of Config. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatConfig struct { - PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"` - PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"` - PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"` - PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"` - PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` - PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` - PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` - Binary *bool `cty:"binary"` - ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` - Inline []string `cty:"inline"` - RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` - Script *string `cty:"script"` - Scripts []string `cty:"scripts"` - ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes"` - Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` - InlineShebang *string `mapstructure:"inline_shebang" cty:"inline_shebang"` - RawPauseAfter *string `mapstructure:"pause_after" cty:"pause_after"` - UseEnvVarFile *bool `mapstructure:"use_env_var_file" cty:"use_env_var_file"` - RemoteFolder *string `mapstructure:"remote_folder" cty:"remote_folder"` - RemoteFile *string `mapstructure:"remote_file" cty:"remote_file"` - RawStartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout"` - SkipClean *bool `mapstructure:"skip_clean" cty:"skip_clean"` - ExpectDisconnect *bool `mapstructure:"expect_disconnect" cty:"expect_disconnect"` + PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"` + PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"` + PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"` + PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"` + PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` + PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` + PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` + Binary *bool `cty:"binary"` + ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` + Inline []string `cty:"inline"` + RemotePath *string `mapstructure:"remote_path" cty:"remote_path"` + Script *string `cty:"script"` + Scripts []string `cty:"scripts"` + ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes"` + Vars []string `mapstructure:"environment_vars" cty:"environment_vars"` + InlineShebang *string `mapstructure:"inline_shebang" cty:"inline_shebang"` + PauseAfter *string `mapstructure:"pause_after" cty:"pause_after"` + UseEnvVarFile *bool `mapstructure:"use_env_var_file" cty:"use_env_var_file"` + RemoteFolder *string `mapstructure:"remote_folder" cty:"remote_folder"` + RemoteFile *string `mapstructure:"remote_file" cty:"remote_file"` + StartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout"` + SkipClean *bool `mapstructure:"skip_clean" cty:"skip_clean"` + ExpectDisconnect *bool `mapstructure:"expect_disconnect" cty:"expect_disconnect"` } // FlatMapstructure returns a new FlatConfig. diff --git a/provisioner/sleep/provisioner.go b/provisioner/sleep/provisioner.go index 0ed9468ec..646f1c4dd 100644 --- a/provisioner/sleep/provisioner.go +++ b/provisioner/sleep/provisioner.go @@ -11,7 +11,7 @@ import ( ) type Provisioner struct { - Duration config.DurationString + Duration time.Duration } var _ packer.Provisioner = new(Provisioner) @@ -24,7 +24,7 @@ func (p *Provisioner) Provision(ctx context.Context, _ packer.Ui, _ packer.Commu select { case <-ctx.Done(): return ctx.Err() - case <-time.After(p.Duration.Duration()): + case <-time.After(p.Duration): return nil } } diff --git a/provisioner/sleep/provisioner_test.go b/provisioner/sleep/provisioner_test.go index d6f047b7a..6ec26c59e 100644 --- a/provisioner/sleep/provisioner_test.go +++ b/provisioner/sleep/provisioner_test.go @@ -4,8 +4,6 @@ import ( "context" "testing" "time" - - "github.com/hashicorp/packer/helper/config" ) func test1sConfig() map[string]interface{} { @@ -22,7 +20,7 @@ func TestConfigPrepare_1s(t *testing.T) { t.Fatalf("prerare failed: %v", err) } - if p.Duration.Duration() != time.Second { + if p.Duration != time.Second { t.Fatal("wrong duration") } } @@ -31,7 +29,7 @@ func TestProvisioner_Provision(t *testing.T) { ctxCancelled, cancel := context.WithCancel(context.Background()) cancel() type fields struct { - Duration config.DurationString + Duration time.Duration } type args struct { ctx context.Context @@ -42,8 +40,8 @@ func TestProvisioner_Provision(t *testing.T) { args args wantErr bool }{ - {"valid sleep", fields{"1ms"}, args{context.Background()}, false}, - {"timeout", fields{"1ms"}, args{ctxCancelled}, true}, + {"valid sleep", fields{1 * time.Millisecond}, args{context.Background()}, false}, + {"timeout", fields{1 * time.Millisecond}, args{ctxCancelled}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/provisioner/windows-restart/provisioner.go b/provisioner/windows-restart/provisioner.go index 528b4eb37..4f019c94b 100644 --- a/provisioner/windows-restart/provisioner.go +++ b/provisioner/windows-restart/provisioner.go @@ -44,7 +44,7 @@ type Config struct { RestartCheckCommand string `mapstructure:"restart_check_command"` // The timeout for waiting for the machine to restart - RestartTimeout config.DurationString `mapstructure:"restart_timeout"` + RestartTimeout time.Duration `mapstructure:"restart_timeout"` // Whether to check the registry (see RegistryKeys) for pending reboots CheckKey bool `mapstructure:"check_registry"` @@ -85,11 +85,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.RestartCheckCommand = DefaultRestartCheckCommand } - if p.config.RestartTimeout == "" { - p.config.RestartTimeout = "5m" - } - if err := p.config.RestartTimeout.Validate(); err != nil { - return err + if p.config.RestartTimeout == 0 { + p.config.RestartTimeout = 5 * time.Minute } if len(p.config.RegistryKeys) == 0 { @@ -110,7 +107,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C var cmd *packer.RemoteCmd command := p.config.RestartCommand - err := retry.Config{StartTimeout: p.config.RestartTimeout.Duration()}.Run(ctx, func(context.Context) error { + err := retry.Config{StartTimeout: p.config.RestartTimeout}.Run(ctx, func(context.Context) error { cmd = &packer.RemoteCmd{Command: command} return cmd.RunWithUi(ctx, comm, ui) }) @@ -130,7 +127,7 @@ var waitForRestart = func(ctx context.Context, p *Provisioner, comm packer.Commu ui := p.ui ui.Say("Waiting for machine to restart...") waitDone := make(chan bool, 1) - timeout := time.After(p.config.RestartTimeout.Duration()) + timeout := time.After(p.config.RestartTimeout) var err error p.comm = comm diff --git a/provisioner/windows-restart/provisioner_test.go b/provisioner/windows-restart/provisioner_test.go index f72608032..ffe9c48a2 100644 --- a/provisioner/windows-restart/provisioner_test.go +++ b/provisioner/windows-restart/provisioner_test.go @@ -31,7 +31,7 @@ func TestProvisionerPrepare_Defaults(t *testing.T) { t.Fatalf("err: %s", err) } - if p.config.RestartTimeout.Duration() != 5*time.Minute { + if p.config.RestartTimeout != 5*time.Minute { t.Errorf("unexpected restart timeout: %s", p.config.RestartTimeout) } @@ -50,7 +50,7 @@ func TestProvisionerPrepare_ConfigRetryTimeout(t *testing.T) { t.Fatalf("err: %s", err) } - if p.config.RestartTimeout.Duration() != 1*time.Minute { + if p.config.RestartTimeout != 1*time.Minute { t.Errorf("unexpected restart timeout: %s", p.config.RestartTimeout) } } diff --git a/provisioner/windows-shell/provisioner.go b/provisioner/windows-shell/provisioner.go index 927d4f5a9..a2927017c 100644 --- a/provisioner/windows-shell/provisioner.go +++ b/provisioner/windows-shell/provisioner.go @@ -35,7 +35,7 @@ type Config struct { // The timeout for retrying to start the process. Until this timeout // is reached, if the provisioner can't start a process, it retries. // This can be set high to allow for reboots. - StartRetryTimeout config.DurationString `mapstructure:"start_retry_timeout"` + StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"` // This is used in the template generation to format environment variables // inside the `ExecuteCommand` template. @@ -79,8 +79,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.Inline = nil } - if p.config.StartRetryTimeout == "" { - p.config.StartRetryTimeout = "5m" + if p.config.StartRetryTimeout == 0 { + p.config.StartRetryTimeout = 5 * time.Minute } if p.config.RemotePath == "" { @@ -202,7 +202,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C // and then the command is executed but the file doesn't exist // any longer. var cmd *packer.RemoteCmd - err = retry.Config{StartTimeout: p.config.StartRetryTimeout.Duration()}.Run(ctx, func(ctx context.Context) error { + err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error { if _, err := f.Seek(0, 0); err != nil { return err } diff --git a/template/parse.go b/template/parse.go index 3088903e9..ff5c60988 100644 --- a/template/parse.go +++ b/template/parse.go @@ -273,7 +273,7 @@ func (r *rawTemplate) decoder( result interface{}, md *mapstructure.Metadata) *mapstructure.Decoder { d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - DecodeHook: nil, + DecodeHook: mapstructure.StringToTimeDurationHookFunc(), Metadata: md, Result: result, }) diff --git a/template/parse_test.go b/template/parse_test.go index 04e41604d..77b63616d 100644 --- a/template/parse_test.go +++ b/template/parse_test.go @@ -9,6 +9,7 @@ import ( "reflect" "strings" "testing" + "time" "github.com/google/go-cmp/cmp" ) @@ -98,7 +99,7 @@ func TestParse(t *testing.T) { Provisioners: []*Provisioner{ { Type: "something", - PauseBefore: "1s", + PauseBefore: 1 * time.Second, }, }, }, @@ -111,7 +112,7 @@ func TestParse(t *testing.T) { Provisioners: []*Provisioner{ { Type: "something", - Timeout: "5m", + Timeout: 5 * time.Minute, }, }, }, @@ -357,12 +358,6 @@ func TestParse(t *testing.T) { false, }, - { - "parse-bad-prov-timeout.json", - nil, - true, - }, - { "parse-comment.json", &Template{ diff --git a/template/template.go b/template/template.go index dd382b3c9..6bab8d4c2 100644 --- a/template/template.go +++ b/template/template.go @@ -6,9 +6,9 @@ import ( "encoding/json" "errors" "fmt" + "time" multierror "github.com/hashicorp/go-multierror" - "github.com/hashicorp/packer/helper/config" ) // Template represents the parsed template that is used to configure @@ -140,8 +140,8 @@ type Provisioner struct { Type string `json:"type"` Config map[string]interface{} `json:"config,omitempty"` Override map[string]interface{} `json:"override,omitempty"` - PauseBefore config.DurationString `mapstructure:"pause_before" json:"pause_before,omitempty"` - Timeout config.DurationString `mapstructure:"timeout" json:"timeout,omitempty"` + PauseBefore time.Duration `mapstructure:"pause_before" json:"pause_before,omitempty"` + Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"` } // MarshalJSON conducts the necessary flattening of the Provisioner struct diff --git a/template/test-fixtures/parse-bad-prov-timeout.json b/template/test-fixtures/parse-bad-prov-timeout.json deleted file mode 100644 index 8a147bb6c..000000000 --- a/template/test-fixtures/parse-bad-prov-timeout.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "builders": [{ - "type": "foo" - }], - - "provisioners": [{ - "timeout": 555, - "type": "bar", - "only": ["foo"] - }] -} diff --git a/website/source/partials/builder/amazon/common/_RunConfig-not-required.html.md b/website/source/partials/builder/amazon/common/_RunConfig-not-required.html.md index 1f625a64b..ecb31ce6d 100644 --- a/website/source/partials/builder/amazon/common/_RunConfig-not-required.html.md +++ b/website/source/partials/builder/amazon/common/_RunConfig-not-required.html.md @@ -279,7 +279,7 @@ subnet_id to be set. If this field is left blank, Packer will try to get the VPC ID from the subnet_id. -- `windows_password_timeout` (duration string. ex: "1h5m2s") - The timeout for waiting for a Windows +- `windows_password_timeout` (duration string | ex: "1h5m2s") - The timeout for waiting for a Windows password for Windows instances. Defaults to 20 minutes. Example value: 10m diff --git a/website/source/partials/builder/azure/arm/_Config-not-required.html.md b/website/source/partials/builder/azure/arm/_Config-not-required.html.md index 8601cee01..b0cc4b5c8 100644 --- a/website/source/partials/builder/azure/arm/_Config-not-required.html.md +++ b/website/source/partials/builder/azure/arm/_Config-not-required.html.md @@ -34,7 +34,7 @@ "managed_image_name": "TargetImageName", "managed_image_resource_group_name": "TargetResourceGroup" -- `shared_image_gallery_timeout` (duration string. ex: "1h5m2s") - How long to wait for an image to be published to the shared image +- `shared_image_gallery_timeout` (duration string | ex: "1h5m2s") - How long to wait for an image to be published to the shared image gallery before timing out. If your Packer build is failing on the Publishing to Shared Image Gallery step with the error `Original Error: context deadline exceeded`, but the image is present when you check your @@ -187,7 +187,7 @@ 3. PlanPublisher 4. PlanPromotionCode -- `polling_duration_timeout` (duration string. ex: "1h5m2s") - The default PollingDuration for azure is 15mins, this property will override +- `polling_duration_timeout` (duration string | ex: "1h5m2s") - The default PollingDuration for azure is 15mins, this property will override that value. See [Azure DefaultPollingDuration](https://godoc.org/github.com/Azure/go-autorest/autorest#pkg-constants) If your Packer build is failing on the ARM deployment step with the error `Original Error: diff --git a/website/source/partials/builder/cloudstack/_Config-not-required.html.md b/website/source/partials/builder/cloudstack/_Config-not-required.html.md index e99070514..bcb74665e 100644 --- a/website/source/partials/builder/cloudstack/_Config-not-required.html.md +++ b/website/source/partials/builder/cloudstack/_Config-not-required.html.md @@ -1,6 +1,6 @@ -- `async_timeout` (duration string. ex: "1h5m2s") - The time duration to wait for async calls to +- `async_timeout` (duration string | ex: "1h5m2s") - The time duration to wait for async calls to finish. Defaults to 30m. - `http_get_only` (bool) - Some cloud providers only allow HTTP GET calls @@ -32,7 +32,7 @@ attached to a virtual machine. Defaults to `false`. This option is only available when using `source_iso`. -- `eject_iso_delay` (duration string. ex: "1h5m2s") - Configure the duration time to wait, making sure virtual machine is able +- `eject_iso_delay` (duration string | ex: "1h5m2s") - Configure the duration time to wait, making sure virtual machine is able to finish installing OS before it ejects safely. Requires `eject_iso` set to `true` and this option is only available when using `source_iso`. diff --git a/website/source/partials/builder/digitalocean/_Config-not-required.html.md b/website/source/partials/builder/digitalocean/_Config-not-required.html.md index 9b994957f..40e39d000 100644 --- a/website/source/partials/builder/digitalocean/_Config-not-required.html.md +++ b/website/source/partials/builder/digitalocean/_Config-not-required.html.md @@ -20,11 +20,11 @@ - `snapshot_regions` ([]string) - The regions of the resulting snapshot that will appear in your account. -- `state_timeout` (duration string. ex: "1h5m2s") - The time to wait, as a duration string, for a +- `state_timeout` (duration string | ex: "1h5m2s") - The time to wait, as a duration string, for a droplet to enter a desired state (such as "active") before timing out. The default state timeout is "6m". -- `snapshot_timeout` (duration string. ex: "1h5m2s") - How long to wait for an image to be published to the shared image +- `snapshot_timeout` (duration string | ex: "1h5m2s") - How long to wait for an image to be published to the shared image gallery before timing out. If your Packer build is failing on the Publishing to Shared Image Gallery step with the error `Original Error: context deadline exceeded`, but the image is present when you check your diff --git a/website/source/partials/builder/googlecompute/_Config-not-required.html.md b/website/source/partials/builder/googlecompute/_Config-not-required.html.md index 4ffb9840e..a9101d361 100644 --- a/website/source/partials/builder/googlecompute/_Config-not-required.html.md +++ b/website/source/partials/builder/googlecompute/_Config-not-required.html.md @@ -88,7 +88,7 @@ - `preemptible` (bool) - If true, launch a preemptible instance. -- `state_timeout` (duration string. ex: "1h5m2s") - The time to wait for instance state changes. Defaults to "5m". +- `state_timeout` (duration string | ex: "1h5m2s") - The time to wait for instance state changes. Defaults to "5m". - `region` (string) - The region in which to launch the instance. Defaults to the region hosting the specified zone. diff --git a/website/source/partials/builder/hyperone/_Config-not-required.html.md b/website/source/partials/builder/hyperone/_Config-not-required.html.md index 743777cc5..1055532c2 100644 --- a/website/source/partials/builder/hyperone/_Config-not-required.html.md +++ b/website/source/partials/builder/hyperone/_Config-not-required.html.md @@ -6,7 +6,7 @@ - `token_login` (string) - Login (an e-mail) on HyperOne platform. Set this if you want to fetch the token by SSH authentication. -- `state_timeout` (duration string. ex: "1h5m2s") - Timeout for waiting on the API to complete +- `state_timeout` (duration string | ex: "1h5m2s") - Timeout for waiting on the API to complete a request. Defaults to 5m. - `image_name` (string) - The name of the resulting image. Defaults to diff --git a/website/source/partials/builder/lxc/_Config-not-required.html.md b/website/source/partials/builder/lxc/_Config-not-required.html.md index d54f4a36d..e81ce2657 100644 --- a/website/source/partials/builder/lxc/_Config-not-required.html.md +++ b/website/source/partials/builder/lxc/_Config-not-required.html.md @@ -11,7 +11,7 @@ as ssh so you can execute packer builds on a remote host. Defaults to Empty. -- `init_timeout` (string) - The timeout in seconds to wait for the the +- `init_timeout` (duration string | ex: "1h5m2s") - The timeout in seconds to wait for the the container to start. Defaults to 20 seconds. - `create_options` ([]string) - Options to pass to lxc-create. For diff --git a/website/source/partials/builder/virtualbox/common/_ShutdownConfig-not-required.html.md b/website/source/partials/builder/virtualbox/common/_ShutdownConfig-not-required.html.md index e734ac3e1..93da47ced 100644 --- a/website/source/partials/builder/virtualbox/common/_ShutdownConfig-not-required.html.md +++ b/website/source/partials/builder/virtualbox/common/_ShutdownConfig-not-required.html.md @@ -8,12 +8,12 @@ since reboots may fail and specify the final shutdown command in your last script. -- `shutdown_timeout` (duration string. ex: "1h5m2s") - The amount of time to wait after executing the +- `shutdown_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait after executing the shutdown_command for the virtual machine to actually shut down. If it doesn't shut down in this time, it is an error. By default, the timeout is 5m or five minutes. -- `post_shutdown_delay` (duration string. ex: "1h5m2s") - The amount of time to wait after shutting +- `post_shutdown_delay` (duration string | ex: "1h5m2s") - The amount of time to wait after shutting down the virtual machine. If you get the error Error removing floppy controller, you might need to set this to 5m or so. By default, the delay is 0s or disabled. diff --git a/website/source/partials/builder/yandex/_Config-not-required.html.md b/website/source/partials/builder/yandex/_Config-not-required.html.md index 80d43eb27..8a0674934 100644 --- a/website/source/partials/builder/yandex/_Config-not-required.html.md +++ b/website/source/partials/builder/yandex/_Config-not-required.html.md @@ -73,6 +73,6 @@ - `zone` (string) - The name of the zone to launch the instance. This defaults to `ru-central1-a`. -- `state_timeout` (duration string. ex: "1h5m2s") - The time to wait for instance state changes. +- `state_timeout` (duration string | ex: "1h5m2s") - The time to wait for instance state changes. Defaults to `5m`. \ No newline at end of file diff --git a/website/source/partials/common/bootcommand/_BootConfig-not-required.html.md b/website/source/partials/common/bootcommand/_BootConfig-not-required.html.md index 526a29c98..3159ff57d 100644 --- a/website/source/partials/common/bootcommand/_BootConfig-not-required.html.md +++ b/website/source/partials/common/bootcommand/_BootConfig-not-required.html.md @@ -1,12 +1,12 @@ -- `boot_keygroup_interval` (duration string. ex: "1h5m2s") - Time to wait after sending a group of key pressses. The value of this +- `boot_keygroup_interval` (duration string | ex: "1h5m2s") - Time to wait after sending a group of key pressses. The value of this should be a duration. Examples are `5s` and `1m30s` which will cause Packer to wait five seconds and one minute 30 seconds, respectively. If this isn't specified, a sensible default value is picked depending on the builder type. -- `boot_wait` (duration string. ex: "1h5m2s") - The time to wait after booting the initial virtual machine before typing +- `boot_wait` (duration string | ex: "1h5m2s") - The time to wait after booting the initial virtual machine before typing the `boot_command`. The value of this should be a duration. Examples are `5s` and `1m30s` which will cause Packer to wait five seconds and one minute 30 seconds, respectively. If this isn't specified, the default is diff --git a/website/source/partials/common/bootcommand/_VNCConfig-not-required.html.md b/website/source/partials/common/bootcommand/_VNCConfig-not-required.html.md index 937b0b467..27cba7b91 100644 --- a/website/source/partials/common/bootcommand/_VNCConfig-not-required.html.md +++ b/website/source/partials/common/bootcommand/_VNCConfig-not-required.html.md @@ -3,5 +3,5 @@ - `disable_vnc` (bool) - Whether to create a VNC connection or not. A boot_command cannot be used when this is true. Defaults to false. -- `boot_key_interval` (duration string. ex: "1h5m2s") - Time in ms to wait between each key press +- `boot_key_interval` (duration string | ex: "1h5m2s") - Time in ms to wait between each key press \ No newline at end of file diff --git a/website/source/partials/common/shutdowncommand/_ShutdownConfig-not-required.html.md b/website/source/partials/common/shutdowncommand/_ShutdownConfig-not-required.html.md index 8d72081d7..6d65b9e46 100644 --- a/website/source/partials/common/shutdowncommand/_ShutdownConfig-not-required.html.md +++ b/website/source/partials/common/shutdowncommand/_ShutdownConfig-not-required.html.md @@ -9,7 +9,7 @@ reboots may fail) and instead specify the final shutdown command in your last script. -- `shutdown_timeout` (duration string. ex: "1h5m2s") - The amount of time to wait after executing the shutdown_command for the +- `shutdown_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait after executing the shutdown_command for the virtual machine to actually shut down. If the machine doesn't shut down in this time it is considered an error. By default, the time out is "5m" (five minutes). diff --git a/website/source/partials/helper/communicator/_Config-not-required.html.md b/website/source/partials/helper/communicator/_Config-not-required.html.md index ec02abbc7..15df6051a 100644 --- a/website/source/partials/helper/communicator/_Config-not-required.html.md +++ b/website/source/partials/helper/communicator/_Config-not-required.html.md @@ -15,7 +15,7 @@ that uses `docker exec` and `docker cp` to execute scripts and copy files. -- `pause_before_connecting` (duration string. ex: "1h5m2s") - We recommend that you enable SSH or WinRM as the very last step in your +- `pause_before_connecting` (duration string | ex: "1h5m2s") - 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. diff --git a/website/source/partials/helper/communicator/_SSH-not-required.html.md b/website/source/partials/helper/communicator/_SSH-not-required.html.md index 1eca3bcd7..2adefaca6 100644 --- a/website/source/partials/helper/communicator/_SSH-not-required.html.md +++ b/website/source/partials/helper/communicator/_SSH-not-required.html.md @@ -36,7 +36,7 @@ - `ssh_pty` (bool) - If `true`, a PTY will be requested for the SSH connection. This defaults to `false`. -- `ssh_timeout` (duration string. ex: "1h5m2s") - The time to wait for SSH to become available. Packer uses this to +- `ssh_timeout` (duration string | ex: "1h5m2s") - The time to wait for SSH to become available. Packer uses this to determine when the machine has booted so this is usually quite long. Example value: `10m`. @@ -79,10 +79,10 @@ - `ssh_proxy_password` (string) - The optional password to use to authenticate with the proxy server. -- `ssh_keep_alive_interval` (duration string. ex: "1h5m2s") - How often to send "keep alive" messages to the server. Set to a negative +- `ssh_keep_alive_interval` (duration string | ex: "1h5m2s") - How often to send "keep alive" messages to the server. Set to a negative value (`-1s`) to disable. Example value: `10s`. Defaults to `5s`. -- `ssh_read_write_timeout` (duration string. ex: "1h5m2s") - The amount of time to wait for a remote command to end. This might be +- `ssh_read_write_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait for a remote command to end. This might be useful if, for example, packer hangs on a connection after a reboot. Example: `5m`. Disabled by default. diff --git a/website/source/partials/helper/communicator/_WinRM-not-required.html.md b/website/source/partials/helper/communicator/_WinRM-not-required.html.md index dbbd58107..d77c4d9df 100644 --- a/website/source/partials/helper/communicator/_WinRM-not-required.html.md +++ b/website/source/partials/helper/communicator/_WinRM-not-required.html.md @@ -14,7 +14,7 @@ unencrypted connection and `5986` for SSL when `winrm_use_ssl` is set to true. -- `winrm_timeout` (duration string. ex: "1h5m2s") - The amount of time to wait for WinRM to become available. This defaults +- `winrm_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait for WinRM to become available. This defaults to `30m` since setting up a Windows machine generally takes a long time. - `winrm_use_ssl` (bool) - If `true`, use HTTPS for WinRM.