Force durations to be passed a strings
Before this commit it was possible to set a duration using an integer or a float. Go's time.Duration is an int64 internally an mapstructure will take advantage of this and load the number as a int64 but `1` means one ns which is unexpected/confusing. To avoid confusion and enforce readability this forces users to pass a string with a unit for a duration; ex "56s".
This commit is contained in:
parent
ada9821897
commit
bf3d9841c6
@ -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 time.Duration `mapstructure:"windows_password_timeout" required:"false"`
|
||||
WindowsPasswordTimeout config.DurationString `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 == 0 {
|
||||
c.WindowsPasswordTimeout = 20 * time.Minute
|
||||
if c.WindowsPasswordTimeout == "" {
|
||||
c.WindowsPasswordTimeout = "20m"
|
||||
}
|
||||
|
||||
if c.RunTags == nil {
|
||||
|
@ -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,
|
||||
Timeout: b.config.WindowsPasswordTimeout.Duration(),
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
|
@ -8,9 +8,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
@ -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,
|
||||
Timeout: b.config.WindowsPasswordTimeout.Duration(),
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
|
@ -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,
|
||||
Timeout: b.config.WindowsPasswordTimeout.Duration(),
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
|
@ -8,11 +8,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
@ -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,
|
||||
Timeout: b.config.WindowsPasswordTimeout.Duration(),
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
|
@ -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,
|
||||
b.config.PollingDurationTimeout,
|
||||
b.config.SharedGalleryTimeout.Duration(),
|
||||
b.config.PollingDurationTimeout.Duration(),
|
||||
spnCloud,
|
||||
spnKeyVault)
|
||||
|
||||
|
@ -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 time.Duration `mapstructure:"shared_image_gallery_timeout"`
|
||||
SharedGalleryTimeout config.DurationString `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 time.Duration `mapstructure:"polling_duration_timeout" required:"false"`
|
||||
PollingDurationTimeout config.DurationString `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 == 0 {
|
||||
c.Comm.SSHTimeout = 20 * time.Minute
|
||||
if c.Comm.SSHTimeout == "" {
|
||||
c.Comm.SSHTimeout = "20m"
|
||||
}
|
||||
|
||||
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 == 0 {
|
||||
if c.SharedGalleryTimeout == "" {
|
||||
// default to a one-hour timeout. In the sdk, the default is 15 m.
|
||||
c.SharedGalleryTimeout = 60 * time.Minute
|
||||
c.SharedGalleryTimeout = "60m"
|
||||
}
|
||||
|
||||
if c.ManagedImageOSDiskSnapshotName != "" {
|
||||
@ -920,9 +920,9 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Polling Duration Timeout
|
||||
if c.PollingDurationTimeout == 0 {
|
||||
if c.PollingDurationTimeout == "" {
|
||||
// In the sdk, the default is 15 m.
|
||||
c.PollingDurationTimeout = 15 * time.Minute
|
||||
c.PollingDurationTimeout = "15m"
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
@ -539,11 +539,11 @@ func TestConfigShouldSupportPackersConfigElements(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if c.Comm.SSHTimeout != 1*time.Hour {
|
||||
if c.Comm.SSHTimeout.Duration() != 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 != 2*time.Hour {
|
||||
if c.Comm.WinRMTimeout.Duration() != 2*time.Hour {
|
||||
t.Errorf("Expected Comm.WinRMTimeout to be a durationof two hours, but got '%s' instead.", c.Comm.WinRMTimeout)
|
||||
}
|
||||
}
|
||||
|
@ -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.Seconds()))
|
||||
client.AsyncTimeout(int64(b.config.AsyncTimeout.Duration().Seconds()))
|
||||
|
||||
// Some CloudStack service providers only allow HTTP GET calls.
|
||||
client.HTTPGETOnly = b.config.HTTPGetOnly
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
@ -35,7 +34,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 time.Duration `mapstructure:"async_timeout" required:"false"`
|
||||
AsyncTimeout config.DurationString `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.
|
||||
@ -68,7 +67,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 time.Duration `mapstructure:"eject_iso_delay"`
|
||||
EjectISODelay config.DurationString `mapstructure:"eject_iso_delay"`
|
||||
// Set to true to expunge the instance when it is
|
||||
// destroyed. Defaults to false.
|
||||
Expunge bool `mapstructure:"expunge" required:"false"`
|
||||
@ -200,8 +199,8 @@ func NewConfig(raws ...interface{}) (*Config, error) {
|
||||
c.SecretKey = os.Getenv("CLOUDSTACK_SECRET_KEY")
|
||||
}
|
||||
|
||||
if c.AsyncTimeout == 0 {
|
||||
c.AsyncTimeout = 30 * time.Minute
|
||||
if c.AsyncTimeout == "" {
|
||||
c.AsyncTimeout = "30m"
|
||||
}
|
||||
|
||||
if len(c.CIDRList) == 0 {
|
||||
|
@ -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 > 0 {
|
||||
if config.EjectISODelay.Duration() > 0 {
|
||||
ui.Message(fmt.Sprintf("Waiting for %v before detaching ISO from virtual machine...", config.EjectISODelay))
|
||||
time.Sleep(config.EjectISODelay)
|
||||
time.Sleep(config.EjectISODelay.Duration())
|
||||
}
|
||||
|
||||
client := state.Get("client").(*cloudstack.CloudStackClient)
|
||||
|
@ -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,
|
||||
snapshotTimeout: b.config.SnapshotTimeout.Duration(),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.StateTimeout != 6*time.Minute {
|
||||
if b.config.StateTimeout.Duration() != 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 != 60*time.Minute {
|
||||
if b.config.SnapshotTimeout.Duration() != 60*time.Minute {
|
||||
t.Errorf("invalid: %s", b.config.SnapshotTimeout)
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
@ -64,7 +63,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 time.Duration `mapstructure:"state_timeout" required:"false"`
|
||||
StateTimeout config.DurationString `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:
|
||||
@ -72,7 +71,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 time.Duration `mapstructure:"snapshot_timeout" required:"false"`
|
||||
SnapshotTimeout config.DurationString `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"`
|
||||
@ -130,18 +129,27 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.DropletName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
|
||||
}
|
||||
|
||||
if c.StateTimeout == 0 {
|
||||
if c.StateTimeout == "" {
|
||||
// Default to 6 minute timeouts waiting for
|
||||
// desired state. i.e waiting for droplet to become active
|
||||
c.StateTimeout = 6 * time.Minute
|
||||
c.StateTimeout = "6m"
|
||||
}
|
||||
|
||||
if c.SnapshotTimeout == 0 {
|
||||
if c.SnapshotTimeout == "" {
|
||||
// Default to 60 minutes timeout, waiting for snapshot action to finish
|
||||
c.SnapshotTimeout = 60 * time.Minute
|
||||
c.SnapshotTimeout = "60m"
|
||||
}
|
||||
|
||||
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...)
|
||||
}
|
||||
|
@ -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)
|
||||
err := waitForDropletState("active", dropletID, client, c.StateTimeout.Duration())
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error waiting for droplet to become active: %s", err)
|
||||
state.Put("error", err)
|
||||
|
@ -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)
|
||||
err = waitForDropletState("off", dropletId, client, c.StateTimeout.Duration())
|
||||
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); err != nil {
|
||||
if err := waitForDropletUnlocked(client, dropletId, c.StateTimeout.Duration()); 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)
|
||||
|
@ -65,7 +65,7 @@ func (s *stepShutdown) Run(ctx context.Context, state multistep.StateBag) multis
|
||||
}
|
||||
}()
|
||||
|
||||
err = waitForDropletState("off", dropletId, client, c.StateTimeout)
|
||||
err = waitForDropletState("off", dropletId, client, c.StateTimeout.Duration())
|
||||
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); err != nil {
|
||||
if err := waitForDropletUnlocked(client, dropletId, c.StateTimeout.Duration()); 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)
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
@ -121,7 +120,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".
|
||||
RawStateTimeout string `mapstructure:"state_timeout" required:"false"`
|
||||
StateTimeout config.DurationString `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"`
|
||||
@ -183,7 +182,6 @@ type Config struct {
|
||||
Zone string `mapstructure:"zone" required:"true"`
|
||||
|
||||
account *jwt.Config
|
||||
stateTimeout time.Duration
|
||||
imageAlreadyExists bool
|
||||
ctx interpolate.Context
|
||||
}
|
||||
@ -293,8 +291,12 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.MachineType = "n1-standard-1"
|
||||
}
|
||||
|
||||
if c.RawStateTimeout == "" {
|
||||
c.RawStateTimeout = "5m"
|
||||
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 es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
|
||||
@ -330,11 +332,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.Region = region
|
||||
}
|
||||
|
||||
err = c.CalcTimeout()
|
||||
if err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
}
|
||||
|
||||
// Authenticating via an account file
|
||||
if c.AccountFile != "" {
|
||||
if c.VaultGCPOauthEngine != "" {
|
||||
@ -384,15 +381,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
return c, nil, nil
|
||||
}
|
||||
|
||||
func (c *Config) CalcTimeout() error {
|
||||
stateTimeout, err := time.ParseDuration(c.RawStateTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed parsing state_timeout: %s", err)
|
||||
}
|
||||
c.stateTimeout = stateTimeout
|
||||
return nil
|
||||
}
|
||||
|
||||
type CustomerEncryptionKey struct {
|
||||
// KmsKeyName: The name of the encryption key that is stored in Google
|
||||
// Cloud KMS.
|
||||
|
@ -82,7 +82,7 @@ type FlatConfig struct {
|
||||
OmitExternalIP *bool `mapstructure:"omit_external_ip" required:"false" cty:"omit_external_ip"`
|
||||
OnHostMaintenance *string `mapstructure:"on_host_maintenance" required:"false" cty:"on_host_maintenance"`
|
||||
Preemptible *bool `mapstructure:"preemptible" required:"false" cty:"preemptible"`
|
||||
RawStateTimeout *string `mapstructure:"state_timeout" required:"false" cty:"state_timeout"`
|
||||
StateTimeout *string `mapstructure:"state_timeout" required:"false" cty:"state_timeout"`
|
||||
Region *string `mapstructure:"region" required:"false" cty:"region"`
|
||||
Scopes []string `mapstructure:"scopes" required:"false" cty:"scopes"`
|
||||
ServiceAccountEmail *string `mapstructure:"service_account_email" required:"false" cty:"service_account_email"`
|
||||
|
@ -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):
|
||||
case <-time.After(config.StateTimeout.Duration()):
|
||||
err = errors.New("time out while waiting for image to register")
|
||||
}
|
||||
|
||||
|
@ -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):
|
||||
case <-time.After(c.StateTimeout.Duration()):
|
||||
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):
|
||||
case <-time.After(config.StateTimeout.Duration()):
|
||||
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):
|
||||
case <-time.After(config.StateTimeout.Duration()):
|
||||
err = errors.New("time out while waiting for disk to delete")
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -232,7 +231,7 @@ func TestStepCreateInstance_errorTimeout(t *testing.T) {
|
||||
errCh := make(chan error, 1)
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
config.stateTimeout = 1 * time.Microsecond
|
||||
config.StateTimeout = "1ms"
|
||||
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
d.RunInstanceErrCh = errCh
|
||||
|
@ -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):
|
||||
case <-time.After(c.StateTimeout.Duration()):
|
||||
err = errors.New("time out while waiting for the password to be created")
|
||||
}
|
||||
}
|
||||
|
@ -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):
|
||||
case <-time.After(config.StateTimeout.Duration()):
|
||||
err = errors.New("time out while waiting for instance to become running")
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ func TestStepInstanceInfo_errorTimeout(t *testing.T) {
|
||||
state.Put("instance_name", "foo")
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
config.stateTimeout = 1 * time.Microsecond
|
||||
config.StateTimeout = "1ms"
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
driver.WaitForInstanceErrCh = errCh
|
||||
|
@ -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):
|
||||
case <-time.After(config.StateTimeout.Duration()):
|
||||
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):
|
||||
case <-time.After(config.StateTimeout.Duration()):
|
||||
err = errors.New("time out while waiting for disk to delete")
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
hcloud.WithPollInterval(b.config.PollInterval.Duration()),
|
||||
hcloud.WithApplication("hcloud-packer", pluginVersion),
|
||||
}
|
||||
b.hcloudClient = hcloud.NewClient(opts...)
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
@ -23,9 +22,10 @@ type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
|
||||
HCloudToken string `mapstructure:"token"`
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
PollInterval time.Duration `mapstructure:"poll_interval"`
|
||||
HCloudToken string `mapstructure:"token"`
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
|
||||
PollInterval config.DurationString `mapstructure:"poll_interval"`
|
||||
|
||||
ServerName string `mapstructure:"server_name"`
|
||||
Location string `mapstructure:"location"`
|
||||
@ -78,8 +78,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.Endpoint = hcloud.Endpoint
|
||||
}
|
||||
}
|
||||
if c.PollInterval == 0 {
|
||||
c.PollInterval = 500 * time.Millisecond
|
||||
if c.PollInterval == "" {
|
||||
c.PollInterval = "500ms"
|
||||
}
|
||||
|
||||
if c.SnapshotName == "" {
|
||||
|
@ -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.Seconds()))
|
||||
prefer := fmt.Sprintf("respond-async,wait=%d", int(b.config.StateTimeout.Duration().Seconds()))
|
||||
cfg.AddDefaultHeader("Prefer", prefer)
|
||||
|
||||
b.client = openapi.NewAPIClient(cfg)
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/json"
|
||||
@ -28,7 +27,7 @@ const (
|
||||
|
||||
defaultDiskType = "ssd"
|
||||
defaultImageService = "564639bc052c084e2f2e3266"
|
||||
defaultStateTimeout = 5 * time.Minute
|
||||
defaultStateTimeout = "5m"
|
||||
defaultUserName = "guru"
|
||||
)
|
||||
|
||||
@ -51,7 +50,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 time.Duration `mapstructure:"state_timeout" required:"false"`
|
||||
StateTimeout config.DurationString `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
|
||||
@ -146,8 +145,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.Comm.SSHUsername = defaultUserName
|
||||
}
|
||||
|
||||
if c.Comm.SSHTimeout == 0 {
|
||||
c.Comm.SSHTimeout = 10 * time.Minute
|
||||
if c.Comm.SSHTimeout == "" {
|
||||
c.Comm.SSHTimeout = "10m"
|
||||
}
|
||||
|
||||
if c.APIURL == "" {
|
||||
@ -174,7 +173,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.Project = cliConfig.Profile.Project.ID
|
||||
}
|
||||
|
||||
if c.StateTimeout == 0 {
|
||||
if c.StateTimeout == "" {
|
||||
c.StateTimeout = defaultStateTimeout
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
SwitchName: b.config.SwitchName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
},
|
||||
|
||||
// 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,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
},
|
||||
|
||||
// wait for the vm to be powered off
|
||||
|
@ -26,10 +26,9 @@ type FlatConfig struct {
|
||||
ISOUrls []string `mapstructure:"iso_urls" cty:"iso_urls"`
|
||||
TargetPath *string `mapstructure:"iso_target_path" cty:"iso_target_path"`
|
||||
TargetExtension *string `mapstructure:"iso_target_extension" cty:"iso_target_extension"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
@ -99,7 +98,7 @@ type FlatConfig struct {
|
||||
SkipExport *bool `mapstructure:"skip_export" required:"false" cty:"skip_export"`
|
||||
Headless *bool `mapstructure:"headless" required:"false" cty:"headless"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
DiskSize *uint `mapstructure:"disk_size" required:"false" cty:"disk_size"`
|
||||
UseLegacyNetworkAdapter *bool `mapstructure:"use_legacy_network_adapter" required:"false" cty:"use_legacy_network_adapter"`
|
||||
DifferencingDisk *bool `mapstructure:"differencing_disk" required:"false" cty:"differencing_disk"`
|
||||
@ -135,7 +134,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
SwitchName: b.config.SwitchName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
},
|
||||
|
||||
// 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,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
},
|
||||
|
||||
// wait for the vm to be powered off
|
||||
|
@ -26,10 +26,9 @@ type FlatConfig struct {
|
||||
ISOUrls []string `mapstructure:"iso_urls" cty:"iso_urls"`
|
||||
TargetPath *string `mapstructure:"iso_target_path" cty:"iso_target_path"`
|
||||
TargetExtension *string `mapstructure:"iso_target_extension" cty:"iso_target_extension"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
@ -99,7 +98,7 @@ type FlatConfig struct {
|
||||
SkipExport *bool `mapstructure:"skip_export" required:"false" cty:"skip_export"`
|
||||
Headless *bool `mapstructure:"headless" required:"false" cty:"headless"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
CloneFromVMCXPath *string `mapstructure:"clone_from_vmcx_path" cty:"clone_from_vmcx_path"`
|
||||
CloneFromVMName *string `mapstructure:"clone_from_vm_name" cty:"clone_from_vm_name"`
|
||||
CloneFromSnapshotName *string `mapstructure:"clone_from_snapshot_name" required:"false" cty:"clone_from_snapshot_name"`
|
||||
@ -137,7 +136,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
@ -32,12 +31,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 time.Duration `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 config.DurationString `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"`
|
||||
@ -78,8 +77,8 @@ func NewConfig(raws ...interface{}) (*Config, error) {
|
||||
c.SSHSourceList = "seciplist:/oracle/public/public-internet"
|
||||
}
|
||||
|
||||
if c.SnapshotTimeout == 0 {
|
||||
c.SnapshotTimeout = 20 * time.Minute
|
||||
if c.SnapshotTimeout == "" {
|
||||
c.SnapshotTimeout = "20m"
|
||||
}
|
||||
|
||||
// Validate that all required fields are present
|
||||
|
@ -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,
|
||||
Timeout: config.SnapshotTimeout.Duration(),
|
||||
}
|
||||
|
||||
snap, err := snapshotClient.CreateSnapshot(snapshotInput)
|
||||
|
@ -1,9 +1,8 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
@ -13,13 +12,13 @@ type SSHConfig struct {
|
||||
|
||||
// These are deprecated, but we keep them around for BC
|
||||
// TODO(@mitchellh): remove
|
||||
SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout"`
|
||||
SSHWaitTimeout config.DurationString `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 != 0 {
|
||||
if c.SSHWaitTimeout != "" {
|
||||
c.Comm.SSHTimeout = c.SSHWaitTimeout
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
HostInterfaces: b.config.HostInterfaces,
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
},
|
||||
&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,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
},
|
||||
¶llelscommon.StepPrlctl{
|
||||
Commands: b.config.PrlctlPost,
|
||||
|
@ -29,10 +29,9 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"`
|
||||
CpuCount *int `mapstructure:"cpus" required:"false" cty:"cpus"`
|
||||
MemorySize *int `mapstructure:"memory" required:"false" cty:"memory"`
|
||||
@ -42,7 +41,7 @@ type FlatConfig struct {
|
||||
PrlctlPost [][]string `mapstructure:"prlctl_post" required:"false" cty:"prlctl_post"`
|
||||
PrlctlVersionFile *string `mapstructure:"prlctl_version_file" required:"false" cty:"prlctl_version_file"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
@ -128,7 +127,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
"cpus": &hcldec.AttrSpec{Name: "cpus", Type: cty.Number, Required: false},
|
||||
"memory": &hcldec.AttrSpec{Name: "memory", Type: cty.Number, Required: false},
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
HostInterfaces: []string{},
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
},
|
||||
&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,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
},
|
||||
&common.StepCleanupTempKeys{
|
||||
Comm: &b.config.SSHConfig.Comm,
|
||||
|
@ -65,11 +65,10 @@ type FlatConfig struct {
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" cty:"ssh_wait_timeout"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
ParallelsToolsFlavor *string `mapstructure:"parallels_tools_flavor" required:"true" cty:"parallels_tools_flavor"`
|
||||
ParallelsToolsGuestPath *string `mapstructure:"parallels_tools_guest_path" required:"false" cty:"parallels_tools_guest_path"`
|
||||
ParallelsToolsMode *string `mapstructure:"parallels_tools_mode" required:"false" cty:"parallels_tools_mode"`
|
||||
@ -148,7 +147,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"parallels_tools_flavor": &hcldec.AttrSpec{Name: "parallels_tools_flavor", Type: cty.String, Required: false},
|
||||
"parallels_tools_guest_path": &hcldec.AttrSpec{Name: "parallels_tools_guest_path", Type: cty.String, Required: false},
|
||||
"parallels_tools_mode": &hcldec.AttrSpec{Name: "parallels_tools_mode", Type: cty.String, Required: false},
|
||||
|
@ -19,10 +19,9 @@ type FlatConfig struct {
|
||||
HTTPDir *string `mapstructure:"http_directory" cty:"http_directory"`
|
||||
HTTPPortMin *int `mapstructure:"http_port_min" cty:"http_port_min"`
|
||||
HTTPPortMax *int `mapstructure:"http_port_max" cty:"http_port_max"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
RawBootKeyInterval *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"`
|
||||
@ -109,7 +108,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"boot_key_interval": &hcldec.AttrSpec{Name: "boot_key_interval", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
|
@ -46,10 +46,10 @@ func (s *stepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if int64(s.BootWait) > 0 {
|
||||
ui.Say(fmt.Sprintf("Waiting %s for boot", s.BootWait.String()))
|
||||
if int64(s.BootWait.Duration()) > 0 {
|
||||
ui.Say(fmt.Sprintf("Waiting %s for boot", s.BootWait))
|
||||
select {
|
||||
case <-time.After(s.BootWait):
|
||||
case <-time.After(s.BootWait.Duration()):
|
||||
break
|
||||
case <-ctx.Done():
|
||||
return multistep.ActionHalt
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/bootcommand"
|
||||
@ -320,7 +319,7 @@ type Config struct {
|
||||
|
||||
// These are deprecated, but we keep them around for BC
|
||||
// TODO(@mitchellh): remove
|
||||
SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout" required:"false"`
|
||||
SSHWaitTimeout config.DurationString `mapstructure:"ssh_wait_timeout" required:"false"`
|
||||
|
||||
// TODO(mitchellh): deprecate
|
||||
RunOnce bool `mapstructure:"run_once"`
|
||||
@ -446,7 +445,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||
}
|
||||
|
||||
// TODO: backwards compatibility, write fixer instead
|
||||
if b.config.SSHWaitTimeout != 0 {
|
||||
if b.config.SSHWaitTimeout != "" {
|
||||
b.config.Comm.SSHTimeout = b.config.SSHWaitTimeout
|
||||
}
|
||||
|
||||
@ -463,6 +462,10 @@ 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"))
|
||||
|
@ -26,14 +26,13 @@ type FlatConfig struct {
|
||||
ISOUrls []string `mapstructure:"iso_urls" cty:"iso_urls"`
|
||||
TargetPath *string `mapstructure:"iso_target_path" cty:"iso_target_path"`
|
||||
TargetExtension *string `mapstructure:"iso_target_extension" cty:"iso_target_extension"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
DisableVNC *bool `mapstructure:"disable_vnc" cty:"disable_vnc"`
|
||||
RawBootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"`
|
||||
BootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
@ -141,7 +140,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"disable_vnc": &hcldec.AttrSpec{Name: "disable_vnc", Type: cty.Bool, Required: false},
|
||||
"boot_key_interval": &hcldec.AttrSpec{Name: "boot_key_interval", Type: cty.String, Required: false},
|
||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||
|
@ -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)
|
||||
<-time.After(config.ShutdownTimeout.Duration())
|
||||
}()
|
||||
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)
|
||||
<-time.After(config.ShutdownTimeout.Duration())
|
||||
}()
|
||||
|
||||
log.Printf("Waiting max %s for shutdown to complete", config.ShutdownTimeout)
|
||||
|
@ -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) > 0 {
|
||||
ui.Say(fmt.Sprintf("Waiting %s for boot...", config.BootWait.String()))
|
||||
if int64(config.BootWait.Duration()) > 0 {
|
||||
ui.Say(fmt.Sprintf("Waiting %s for boot...", config.BootWait))
|
||||
select {
|
||||
case <-time.After(config.BootWait):
|
||||
case <-time.After(config.BootWait.Duration()):
|
||||
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)
|
||||
d := bootcommand.NewVNCDriver(c, config.VNCConfig.BootKeyInterval.Duration())
|
||||
|
||||
ui.Say("Typing the boot command over VNC...")
|
||||
command, err := interpolate.Render(config.VNCConfig.FlatBootCommand(), &configCtx)
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/bootcommand"
|
||||
@ -155,8 +154,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||
b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName)
|
||||
}
|
||||
|
||||
if b.config.Comm.SSHTimeout == 0 {
|
||||
b.config.Comm.SSHTimeout = 10 * time.Minute
|
||||
if b.config.Comm.SSHTimeout == "" {
|
||||
b.config.Comm.SSHTimeout = "10m"
|
||||
}
|
||||
|
||||
if b.config.Comm.Type != "ssh" {
|
||||
|
@ -29,10 +29,9 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_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"`
|
||||
@ -130,7 +129,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
||||
|
@ -4,8 +4,8 @@ package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
@ -22,35 +22,29 @@ 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.
|
||||
RawShutdownTimeout string `mapstructure:"shutdown_timeout" required:"false"`
|
||||
ShutdownTimeout config.DurationString `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.
|
||||
RawPostShutdownDelay string `mapstructure:"post_shutdown_delay" required:"false"`
|
||||
|
||||
ShutdownTimeout time.Duration ``
|
||||
PostShutdownDelay time.Duration ``
|
||||
PostShutdownDelay config.DurationString `mapstructure:"post_shutdown_delay" required:"false"`
|
||||
}
|
||||
|
||||
func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.RawShutdownTimeout == "" {
|
||||
c.RawShutdownTimeout = "5m"
|
||||
if c.ShutdownTimeout == "" {
|
||||
c.ShutdownTimeout = "5m"
|
||||
}
|
||||
|
||||
if c.RawPostShutdownDelay == "" {
|
||||
c.RawPostShutdownDelay = "0s"
|
||||
if c.PostShutdownDelay == "" {
|
||||
c.PostShutdownDelay = "0s"
|
||||
}
|
||||
|
||||
var errs []error
|
||||
var err error
|
||||
c.ShutdownTimeout, err = time.ParseDuration(c.RawShutdownTimeout)
|
||||
if err != nil {
|
||||
if err := c.ShutdownTimeout.Validate(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
|
||||
}
|
||||
|
||||
c.PostShutdownDelay, err = time.ParseDuration(c.RawPostShutdownDelay)
|
||||
if err != nil {
|
||||
if err := c.PostShutdownDelay.Validate(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing post_shutdown_delay: %s", err))
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ func TestShutdownConfigPrepare_ShutdownTimeout(t *testing.T) {
|
||||
|
||||
// Test with a bad value
|
||||
c = testShutdownConfig()
|
||||
c.RawShutdownTimeout = "this is not good"
|
||||
c.ShutdownTimeout = "this is not good"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatalf("should have error")
|
||||
@ -36,12 +36,12 @@ func TestShutdownConfigPrepare_ShutdownTimeout(t *testing.T) {
|
||||
|
||||
// Test with a good one
|
||||
c = testShutdownConfig()
|
||||
c.RawShutdownTimeout = "5s"
|
||||
c.ShutdownTimeout = "5s"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
if c.ShutdownTimeout != 5*time.Second {
|
||||
if c.ShutdownTimeout.Duration() != 5*time.Second {
|
||||
t.Fatalf("bad: %s", c.ShutdownTimeout)
|
||||
}
|
||||
}
|
||||
@ -52,7 +52,7 @@ func TestShutdownConfigPrepare_PostShutdownDelay(t *testing.T) {
|
||||
|
||||
// Test with a bad value
|
||||
c = testShutdownConfig()
|
||||
c.RawPostShutdownDelay = "this is not good"
|
||||
c.PostShutdownDelay = "this is not good"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatalf("should have error")
|
||||
@ -60,23 +60,23 @@ func TestShutdownConfigPrepare_PostShutdownDelay(t *testing.T) {
|
||||
|
||||
// Test with default value
|
||||
c = testShutdownConfig()
|
||||
c.RawPostShutdownDelay = ""
|
||||
c.PostShutdownDelay = ""
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
if c.PostShutdownDelay.Nanoseconds() != 0 {
|
||||
if c.PostShutdownDelay.Duration().Nanoseconds() != 0 {
|
||||
t.Fatalf("bad: %s", c.PostShutdownDelay)
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
c = testShutdownConfig()
|
||||
c.RawPostShutdownDelay = "5s"
|
||||
c.PostShutdownDelay = "5s"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
if c.PostShutdownDelay != 5*time.Second {
|
||||
if c.PostShutdownDelay.Duration() != 5*time.Second {
|
||||
t.Fatalf("bad: %s", c.PostShutdownDelay)
|
||||
}
|
||||
}
|
||||
|
@ -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 time.Duration `mapstructure:"ssh_wait_timeout"`
|
||||
SSHWaitTimeout config.DurationString `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 != 0 {
|
||||
if c.SSHWaitTimeout != "" {
|
||||
c.Comm.SSHTimeout = c.SSHWaitTimeout
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
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,
|
||||
Delay: b.config.PostShutdownDelay,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
Delay: b.config.PostShutdownDelay.Duration(),
|
||||
},
|
||||
&vboxcommon.StepRemoveDevices{
|
||||
Bundling: b.config.VBoxBundleConfig,
|
||||
|
@ -29,10 +29,9 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
Format *string `mapstructure:"format" required:"false" cty:"format"`
|
||||
ExportOpts []string `mapstructure:"export_opts" required:"false" cty:"export_opts"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"`
|
||||
@ -41,8 +40,8 @@ type FlatConfig struct {
|
||||
VRDPPortMin *int `mapstructure:"vrdp_port_min" required:"false" cty:"vrdp_port_min"`
|
||||
VRDPPortMax *int `mapstructure:"vrdp_port_max" cty:"vrdp_port_max"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
RawPostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
PostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
@ -144,7 +143,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false},
|
||||
"export_opts": &hcldec.AttrSpec{Name: "export_opts", Type: cty.List(cty.String), Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
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,
|
||||
Delay: b.config.PostShutdownDelay,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
Delay: b.config.PostShutdownDelay.Duration(),
|
||||
},
|
||||
&vboxcommon.StepRemoveDevices{
|
||||
GuestAdditionsInterface: b.config.GuestAdditionsInterface,
|
||||
|
@ -22,10 +22,9 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
Format *string `mapstructure:"format" required:"false" cty:"format"`
|
||||
ExportOpts []string `mapstructure:"export_opts" required:"false" cty:"export_opts"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"`
|
||||
@ -78,8 +77,8 @@ type FlatConfig struct {
|
||||
SSHSkipNatMapping *bool `mapstructure:"ssh_skip_nat_mapping" required:"false" cty:"ssh_skip_nat_mapping"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" cty:"ssh_wait_timeout"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
RawPostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
PostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
|
||||
VBoxManage [][]string `mapstructure:"vboxmanage" required:"false" cty:"vboxmanage"`
|
||||
VBoxManagePost [][]string `mapstructure:"vboxmanage_post" required:"false" cty:"vboxmanage_post"`
|
||||
VBoxVersionFile *string `mapstructure:"virtualbox_version_file" required:"false" cty:"virtualbox_version_file"`
|
||||
@ -124,7 +123,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false},
|
||||
"export_opts": &hcldec.AttrSpec{Name: "export_opts", Type: cty.List(cty.String), Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval,
|
||||
GroupInterval: b.config.BootConfig.BootGroupInterval.Duration(),
|
||||
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,
|
||||
Delay: b.config.PostShutdownDelay,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
Delay: b.config.PostShutdownDelay.Duration(),
|
||||
},
|
||||
&vboxcommon.StepVBoxManage{
|
||||
Commands: b.config.VBoxManagePost,
|
||||
|
@ -71,8 +71,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c.GuestAdditionsPath = "VBoxGuestAdditions.iso"
|
||||
}
|
||||
|
||||
if c.RawPostShutdownDelay == "" {
|
||||
c.RawPostShutdownDelay = "2s"
|
||||
if c.PostShutdownDelay == "" {
|
||||
c.PostShutdownDelay = "2s"
|
||||
}
|
||||
|
||||
// Prepare the errors
|
||||
@ -88,7 +88,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(&c.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...)
|
||||
|
||||
log.Printf("PostShutdownDelay: %f", c.PostShutdownDelay.Seconds())
|
||||
log.Printf("PostShutdownDelay: %s", c.PostShutdownDelay)
|
||||
|
||||
if c.VMName == "" {
|
||||
errs = packer.MultiErrorAppend(errs,
|
||||
|
@ -22,10 +22,9 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
Format *string `mapstructure:"format" required:"false" cty:"format"`
|
||||
ExportOpts []string `mapstructure:"export_opts" required:"false" cty:"export_opts"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"`
|
||||
@ -78,8 +77,8 @@ type FlatConfig struct {
|
||||
SSHSkipNatMapping *bool `mapstructure:"ssh_skip_nat_mapping" required:"false" cty:"ssh_skip_nat_mapping"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" cty:"ssh_wait_timeout"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
RawPostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
PostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
|
||||
VBoxManage [][]string `mapstructure:"vboxmanage" required:"false" cty:"vboxmanage"`
|
||||
VBoxManagePost [][]string `mapstructure:"vboxmanage_post" required:"false" cty:"vboxmanage_post"`
|
||||
VBoxVersionFile *string `mapstructure:"virtualbox_version_file" required:"false" cty:"virtualbox_version_file"`
|
||||
@ -120,7 +119,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false},
|
||||
"export_opts": &hcldec.AttrSpec{Name: "export_opts", Type: cty.List(cty.String), Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
|
@ -3,9 +3,8 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
@ -17,12 +16,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 time.Duration `mapstructure:"ssh_wait_timeout"`
|
||||
SSHWaitTimeout config.DurationString `mapstructure:"ssh_wait_timeout"`
|
||||
}
|
||||
|
||||
func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
// TODO: backwards compatibility, write fixer instead
|
||||
if c.SSHWaitTimeout != 0 {
|
||||
if c.SSHWaitTimeout != "" {
|
||||
c.Comm.SSHTimeout = c.SSHWaitTimeout
|
||||
}
|
||||
if c.SSHSkipRequestPty {
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
VNCEnabled: !b.config.DisableVNC,
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
KeyInterval: b.config.VNCConfig.BootKeyInterval,
|
||||
KeyInterval: b.config.VNCConfig.BootKeyInterval.Duration(),
|
||||
},
|
||||
&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,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
},
|
||||
&vmwcommon.StepCleanFiles{},
|
||||
&vmwcommon.StepCompactDisk{
|
||||
|
@ -29,12 +29,11 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
DisableVNC *bool `mapstructure:"disable_vnc" cty:"disable_vnc"`
|
||||
RawBootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"`
|
||||
BootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"`
|
||||
FusionAppPath *string `mapstructure:"fusion_app_path" required:"false" cty:"fusion_app_path"`
|
||||
RemoteType *string `mapstructure:"remote_type" required:"false" cty:"remote_type"`
|
||||
RemoteDatastore *string `mapstructure:"remote_datastore" required:"false" cty:"remote_datastore"`
|
||||
@ -62,7 +61,7 @@ type FlatConfig struct {
|
||||
VNCPortMax *int `mapstructure:"vnc_port_max" cty:"vnc_port_max"`
|
||||
VNCDisablePassword *bool `mapstructure:"vnc_disable_password" required:"false" cty:"vnc_disable_password"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
@ -161,7 +160,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"disable_vnc": &hcldec.AttrSpec{Name: "disable_vnc", Type: cty.Bool, Required: false},
|
||||
"boot_key_interval": &hcldec.AttrSpec{Name: "boot_key_interval", Type: cty.String, Required: false},
|
||||
"fusion_app_path": &hcldec.AttrSpec{Name: "fusion_app_path", Type: cty.String, Required: false},
|
||||
|
@ -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,
|
||||
BootWait: b.config.BootWait.Duration(),
|
||||
VNCEnabled: !b.config.DisableVNC,
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
KeyInterval: b.config.VNCConfig.BootKeyInterval,
|
||||
KeyInterval: b.config.VNCConfig.BootKeyInterval.Duration(),
|
||||
},
|
||||
&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,
|
||||
Timeout: b.config.ShutdownTimeout.Duration(),
|
||||
},
|
||||
&vmwcommon.StepCleanFiles{},
|
||||
&vmwcommon.StepCompactDisk{
|
||||
|
@ -22,12 +22,11 @@ type FlatConfig struct {
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label"`
|
||||
RawBootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval"`
|
||||
RawBootWait *string `mapstructure:"boot_wait" cty:"boot_wait"`
|
||||
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"`
|
||||
BootGroupInterval *string `cty:"boot_group_interval"`
|
||||
DisableVNC *bool `mapstructure:"disable_vnc" cty:"disable_vnc"`
|
||||
RawBootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"`
|
||||
BootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval"`
|
||||
FusionAppPath *string `mapstructure:"fusion_app_path" required:"false" cty:"fusion_app_path"`
|
||||
RemoteType *string `mapstructure:"remote_type" required:"false" cty:"remote_type"`
|
||||
RemoteDatastore *string `mapstructure:"remote_datastore" required:"false" cty:"remote_datastore"`
|
||||
@ -46,7 +45,7 @@ type FlatConfig struct {
|
||||
VNCPortMax *int `mapstructure:"vnc_port_max" cty:"vnc_port_max"`
|
||||
VNCDisablePassword *bool `mapstructure:"vnc_disable_password" required:"false" cty:"vnc_disable_password"`
|
||||
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
|
||||
RawShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
@ -130,7 +129,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_group_interval": &hcldec.AttrSpec{Name: "boot_group_interval", Type: cty.String, Required: false},
|
||||
"disable_vnc": &hcldec.AttrSpec{Name: "disable_vnc", Type: cty.Bool, Required: false},
|
||||
"boot_key_interval": &hcldec.AttrSpec{Name: "boot_key_interval", Type: cty.String, Required: false},
|
||||
"fusion_app_path": &hcldec.AttrSpec{Name: "fusion_app_path", Type: cty.String, Required: false},
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
@ -119,7 +118,7 @@ type Config struct {
|
||||
ctx interpolate.Context
|
||||
// The time to wait for instance state changes.
|
||||
// Defaults to `5m`.
|
||||
StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"`
|
||||
StateTimeout config.DurationString `mapstructure:"state_timeout" required:"false"`
|
||||
}
|
||||
|
||||
func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
@ -280,8 +279,12 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if c.StateTimeout == 0 {
|
||||
c.StateTimeout = 5 * time.Minute
|
||||
if c.StateTimeout == "" {
|
||||
c.StateTimeout = "5m"
|
||||
}
|
||||
|
||||
if err := c.StateTimeout.Validate(); err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
}
|
||||
|
||||
// Check for any errors.
|
||||
|
@ -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)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.StateTimeout.Duration())
|
||||
defer cancel()
|
||||
|
||||
op, err := sdk.WrapOperation(sdk.Compute().Image().Create(ctx, &compute.CreateImageRequest{
|
||||
|
@ -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)
|
||||
ctx, cancel := context.WithTimeout(ctx, config.StateTimeout.Duration())
|
||||
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)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), config.StateTimeout.Duration())
|
||||
defer cancel()
|
||||
|
||||
if s.SerialLogFile != "" {
|
||||
|
@ -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)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.StateTimeout.Duration())
|
||||
defer cancel()
|
||||
|
||||
instance, err := sdk.Compute().Instance().Get(ctx, &compute.GetInstanceRequest{
|
||||
|
@ -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)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.StateTimeout.Duration())
|
||||
defer cancel()
|
||||
op, err := sdk.WrapOperation(sdk.Compute().Instance().Stop(ctx, &compute.StopInstanceRequest{
|
||||
InstanceId: instanceID,
|
||||
|
@ -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":
|
||||
case "time.Duration", "github.com/hashicorp/packer/helper/config.DurationString":
|
||||
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())
|
||||
|
@ -111,6 +111,10 @@ 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\""
|
||||
}
|
||||
|
||||
field := Field{
|
||||
Name: name,
|
||||
|
@ -5,8 +5,8 @@ package bootcommand
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
@ -112,21 +112,19 @@ 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.
|
||||
RawBootGroupInterval string `mapstructure:"boot_keygroup_interval"`
|
||||
BootGroupInterval config.DurationString `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.
|
||||
RawBootWait string `mapstructure:"boot_wait"`
|
||||
BootWait config.DurationString `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
|
||||
// well, and are covered in the section below on the boot command. If this
|
||||
// is not specified, it is assumed the installer will start itself.
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
BootGroupInterval time.Duration ``
|
||||
BootWait time.Duration ``
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
}
|
||||
|
||||
// The boot command "typed" character for character over a VNC connection to
|
||||
@ -142,37 +140,26 @@ type VNCConfig struct {
|
||||
// when this is true. Defaults to false.
|
||||
DisableVNC bool `mapstructure:"disable_vnc"`
|
||||
// Time in ms to wait between each key press
|
||||
RawBootKeyInterval string `mapstructure:"boot_key_interval"`
|
||||
BootKeyInterval time.Duration ``
|
||||
BootKeyInterval config.DurationString `mapstructure:"boot_key_interval"`
|
||||
}
|
||||
|
||||
func (c *BootConfig) Prepare(ctx *interpolate.Context) (errs []error) {
|
||||
if c.RawBootWait == "" {
|
||||
c.RawBootWait = "10s"
|
||||
if c.BootWait == "" {
|
||||
c.BootWait = "10s"
|
||||
}
|
||||
|
||||
if c.RawBootWait != "" {
|
||||
bw, err := time.ParseDuration(c.RawBootWait)
|
||||
if err != nil {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
|
||||
} else {
|
||||
c.BootWait = bw
|
||||
}
|
||||
if err := c.BootWait.Validate(); err != nil {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
|
||||
}
|
||||
|
||||
if c.RawBootGroupInterval == "" {
|
||||
c.RawBootGroupInterval = "0ms"
|
||||
if c.BootGroupInterval == "" {
|
||||
c.BootGroupInterval = "0ms"
|
||||
}
|
||||
|
||||
if c.RawBootGroupInterval != "" {
|
||||
bgi, err := time.ParseDuration(c.RawBootGroupInterval)
|
||||
if err != nil {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("Failed parsing boot_keygroup_interval: %s", err))
|
||||
} else {
|
||||
c.BootGroupInterval = bgi
|
||||
}
|
||||
if err := c.BootGroupInterval.Validate(); err != nil {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("Failed parsing boot_keygroup_interval: %s", err))
|
||||
}
|
||||
|
||||
if c.BootCommand != nil {
|
||||
@ -197,18 +184,13 @@ func (c *VNCConfig) Prepare(ctx *interpolate.Context) (errs []error) {
|
||||
fmt.Errorf("A boot command cannot be used when vnc is disabled."))
|
||||
}
|
||||
|
||||
if c.RawBootKeyInterval == "" {
|
||||
c.RawBootKeyInterval = "0ms"
|
||||
if c.BootKeyInterval == "" {
|
||||
c.BootKeyInterval = "0ms"
|
||||
}
|
||||
|
||||
if c.RawBootKeyInterval != "" {
|
||||
bki, err := time.ParseDuration(c.RawBootKeyInterval)
|
||||
if err != nil {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("Failed parsing boot_key_interval: %s", err))
|
||||
} else {
|
||||
c.BootKeyInterval = bki
|
||||
}
|
||||
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)...)
|
||||
|
@ -11,18 +11,18 @@ func TestConfigPrepare(t *testing.T) {
|
||||
|
||||
// Test a default boot_wait
|
||||
c = new(BootConfig)
|
||||
c.RawBootWait = ""
|
||||
c.BootWait = ""
|
||||
errs := c.Prepare(&interpolate.Context{})
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("bad: %#v", errs)
|
||||
}
|
||||
if c.RawBootWait != "10s" {
|
||||
t.Fatalf("bad value: %s", c.RawBootWait)
|
||||
if c.BootWait != "10s" {
|
||||
t.Fatalf("bad value: %s", c.BootWait)
|
||||
}
|
||||
|
||||
// Test with a bad boot_wait
|
||||
c = new(BootConfig)
|
||||
c.RawBootWait = "this is not good"
|
||||
c.BootWait = "this is not good"
|
||||
errs = c.Prepare(&interpolate.Context{})
|
||||
if len(errs) == 0 {
|
||||
t.Fatal("should error")
|
||||
@ -30,7 +30,7 @@ func TestConfigPrepare(t *testing.T) {
|
||||
|
||||
// Test with a good one
|
||||
c = new(BootConfig)
|
||||
c.RawBootWait = "5s"
|
||||
c.BootWait = "5s"
|
||||
errs = c.Prepare(&interpolate.Context{})
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("bad: %#v", errs)
|
||||
|
@ -3,9 +3,7 @@
|
||||
package shutdowncommand
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
@ -23,22 +21,17 @@ 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).
|
||||
RawShutdownTimeout string `mapstructure:"shutdown_timeout" required:"false"`
|
||||
|
||||
ShutdownTimeout time.Duration ``
|
||||
ShutdownTimeout config.DurationString `mapstructure:"shutdown_timeout" required:"false"`
|
||||
}
|
||||
|
||||
func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.RawShutdownTimeout == "" {
|
||||
c.RawShutdownTimeout = "5m"
|
||||
if c.ShutdownTimeout == "" {
|
||||
c.ShutdownTimeout = "5m"
|
||||
}
|
||||
|
||||
var errs []error
|
||||
var err error
|
||||
c.ShutdownTimeout, err = time.ParseDuration(c.RawShutdownTimeout)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
|
||||
if err := c.ShutdownTimeout.Validate(); err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
|
||||
return errs
|
||||
return nil
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func TestShutdownConfigPrepare_ShutdownTimeout(t *testing.T) {
|
||||
|
||||
// Test with a bad value
|
||||
c = testShutdownConfig()
|
||||
c.RawShutdownTimeout = "this is not good"
|
||||
c.ShutdownTimeout = "this is not good"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatalf("should have error")
|
||||
@ -36,12 +36,12 @@ func TestShutdownConfigPrepare_ShutdownTimeout(t *testing.T) {
|
||||
|
||||
// Test with a good one
|
||||
c = testShutdownConfig()
|
||||
c.RawShutdownTimeout = "5s"
|
||||
c.ShutdownTimeout = "5s"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
if c.ShutdownTimeout != 5*time.Second {
|
||||
if c.ShutdownTimeout.Duration() != 5*time.Second {
|
||||
t.Fatalf("bad: %s", c.ShutdownTimeout)
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ func TestParser_ParseFile(t *testing.T) {
|
||||
RawSingleISOUrl: strPtr("http://releases.ubuntu.com/12.04/ubuntu-12.04.5-server-amd64.iso"),
|
||||
BootCommand: []string{"..."},
|
||||
ShutdownCommand: strPtr("echo 'vagrant' | sudo -S shutdown -P now"),
|
||||
RawBootWait: strPtr("10s"),
|
||||
BootWait: strPtr("10s"),
|
||||
VBoxManage: [][]string{},
|
||||
VBoxManagePost: [][]string{},
|
||||
},
|
||||
|
@ -52,7 +52,7 @@ func TestParser_Parse(t *testing.T) {
|
||||
RawSingleISOUrl: strPtr("http://releases.ubuntu.com/12.04/ubuntu-12.04.5-server-amd64.iso"),
|
||||
BootCommand: []string{"..."},
|
||||
ShutdownCommand: strPtr("echo 'vagrant' | sudo -S shutdown -P now"),
|
||||
RawBootWait: strPtr("10s"),
|
||||
BootWait: strPtr("10s"),
|
||||
VBoxManage: [][]string{},
|
||||
VBoxManagePost: [][]string{},
|
||||
},
|
||||
|
@ -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 time.Duration `mapstructure:"pause_before_connecting"`
|
||||
PauseBeforeConnect config.DurationString `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 time.Duration `mapstructure:"ssh_timeout"`
|
||||
SSHTimeout config.DurationString `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 time.Duration `mapstructure:"ssh_keep_alive_interval"`
|
||||
SSHKeepAliveInterval config.DurationString `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 time.Duration `mapstructure:"ssh_read_write_timeout"`
|
||||
SSHReadWriteTimeout config.DurationString `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 time.Duration `mapstructure:"winrm_timeout"`
|
||||
WinRMTimeout config.DurationString `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 == 0 {
|
||||
c.SSHTimeout = 5 * time.Minute
|
||||
if c.SSHTimeout == "" {
|
||||
c.SSHTimeout = "5m"
|
||||
}
|
||||
|
||||
if c.SSHKeepAliveInterval == 0 {
|
||||
c.SSHKeepAliveInterval = 5 * time.Second
|
||||
if c.SSHKeepAliveInterval == "" {
|
||||
c.SSHKeepAliveInterval = "5s"
|
||||
}
|
||||
|
||||
if c.SSHHandshakeAttempts == 0 {
|
||||
@ -404,6 +404,13 @@ 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\"."))
|
||||
}
|
||||
@ -470,22 +477,25 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
|
||||
return errs
|
||||
}
|
||||
|
||||
func (c *Config) prepareWinRM(ctx *interpolate.Context) []error {
|
||||
func (c *Config) prepareWinRM(ctx *interpolate.Context) (errs []error) {
|
||||
if c.WinRMPort == 0 && c.WinRMUseSSL {
|
||||
c.WinRMPort = 5986
|
||||
} else if c.WinRMPort == 0 {
|
||||
c.WinRMPort = 5985
|
||||
}
|
||||
|
||||
if c.WinRMTimeout == 0 {
|
||||
c.WinRMTimeout = 30 * time.Minute
|
||||
if c.WinRMTimeout == "" {
|
||||
c.WinRMTimeout = "30m"
|
||||
}
|
||||
|
||||
if err := c.WinRMTimeout.Validate(); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
if c.WinRMUseNTLM == true {
|
||||
c.WinRMTransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
|
||||
}
|
||||
|
||||
var errs []error
|
||||
if c.WinRMUser == "" {
|
||||
errs = append(errs, errors.New("winrm_username must be specified."))
|
||||
}
|
||||
|
@ -112,8 +112,8 @@ func (s *StepConnect) Run(ctx context.Context, state multistep.StateBag) multist
|
||||
return action
|
||||
}
|
||||
|
||||
if s.Config.PauseBeforeConnect > 0 {
|
||||
cancelled := s.pause(s.Config.PauseBeforeConnect, ctx)
|
||||
if s.Config.PauseBeforeConnect.Duration() > 0 {
|
||||
cancelled := s.pause(s.Config.PauseBeforeConnect.Duration(), ctx)
|
||||
if cancelled {
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
@ -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)
|
||||
timeout := time.After(s.Config.SSHTimeout.Duration())
|
||||
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,
|
||||
Timeout: s.Config.SSHReadWriteTimeout,
|
||||
KeepAliveInterval: s.Config.SSHKeepAliveInterval.Duration(),
|
||||
Timeout: s.Config.SSHReadWriteTimeout.Duration(),
|
||||
Tunnels: tunnels,
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
timeout := time.After(s.Config.WinRMTimeout.Duration())
|
||||
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,
|
||||
Timeout: s.Config.WinRMTimeout.Duration(),
|
||||
Https: s.Config.WinRMUseSSL,
|
||||
Insecure: s.Config.WinRMInsecure,
|
||||
TransportDecorator: s.Config.WinRMTransportDecorator,
|
||||
|
@ -31,7 +31,6 @@ var DefaultDecodeHookFuncs = []mapstructure.DecodeHookFunc{
|
||||
uint8ToStringHook,
|
||||
stringToTrilean,
|
||||
mapstructure.StringToSliceHookFunc(","),
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
}
|
||||
|
||||
// Decode decodes the configuration into the target and optionally
|
||||
|
@ -3,7 +3,6 @@ package config
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
@ -12,7 +11,7 @@ func TestDecode(t *testing.T) {
|
||||
type Target struct {
|
||||
Name string
|
||||
Address string
|
||||
Time time.Duration
|
||||
Time DurationString
|
||||
Trilean Trilean
|
||||
}
|
||||
|
||||
@ -31,7 +30,7 @@ func TestDecode(t *testing.T) {
|
||||
},
|
||||
&Target{
|
||||
Name: "bar",
|
||||
Time: 5 * time.Second,
|
||||
Time: "5s",
|
||||
Trilean: TriTrue,
|
||||
},
|
||||
nil,
|
||||
|
36
helper/config/duration.go
Normal file
36
helper/config/duration.go
Normal file
@ -0,0 +1,36 @@
|
||||
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
|
||||
}
|
@ -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 > 0 {
|
||||
if rawP.PauseBefore != "" {
|
||||
provisioner = &PausedProvisioner{
|
||||
PauseBefore: rawP.PauseBefore,
|
||||
PauseBefore: rawP.PauseBefore.Duration(),
|
||||
Provisioner: provisioner,
|
||||
}
|
||||
} else if rawP.Timeout > 0 {
|
||||
} else if rawP.Timeout != "" {
|
||||
provisioner = &TimeoutProvisioner{
|
||||
Timeout: rawP.Timeout,
|
||||
Timeout: rawP.Timeout.Duration(),
|
||||
Provisioner: provisioner,
|
||||
}
|
||||
}
|
||||
|
@ -35,16 +35,17 @@ type Config struct {
|
||||
SpacesKey string `mapstructure:"spaces_key"`
|
||||
SpacesSecret string `mapstructure:"spaces_secret"`
|
||||
|
||||
SpacesRegion string `mapstructure:"spaces_region"`
|
||||
SpaceName string `mapstructure:"space_name"`
|
||||
ObjectName string `mapstructure:"space_object_name"`
|
||||
SkipClean bool `mapstructure:"skip_clean"`
|
||||
Tags []string `mapstructure:"image_tags"`
|
||||
Name string `mapstructure:"image_name"`
|
||||
Description string `mapstructure:"image_description"`
|
||||
Distribution string `mapstructure:"image_distribution"`
|
||||
ImageRegions []string `mapstructure:"image_regions"`
|
||||
Timeout time.Duration `mapstructure:"timeout"`
|
||||
SpacesRegion string `mapstructure:"spaces_region"`
|
||||
SpaceName string `mapstructure:"space_name"`
|
||||
ObjectName string `mapstructure:"space_object_name"`
|
||||
SkipClean bool `mapstructure:"skip_clean"`
|
||||
Tags []string `mapstructure:"image_tags"`
|
||||
Name string `mapstructure:"image_name"`
|
||||
Description string `mapstructure:"image_description"`
|
||||
Distribution string `mapstructure:"image_distribution"`
|
||||
ImageRegions []string `mapstructure:"image_regions"`
|
||||
|
||||
Timeout config.DurationString `mapstructure:"timeout"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
@ -103,8 +104,8 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
p.config.Distribution = "Unkown"
|
||||
}
|
||||
|
||||
if p.config.Timeout == 0 {
|
||||
p.config.Timeout = 20 * time.Minute
|
||||
if p.config.Timeout == "" {
|
||||
p.config.Timeout = "20m"
|
||||
}
|
||||
|
||||
errs := new(packer.MultiError)
|
||||
@ -207,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)
|
||||
err = waitUntilImageAvailable(client, image.ID, p.config.Timeout.Duration())
|
||||
if err != nil {
|
||||
return nil, false, false, fmt.Errorf("Import of image %s failed with error: %s", p.config.Name, err)
|
||||
}
|
||||
@ -221,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)
|
||||
err = distributeImageToRegions(client, image.ID, regions, p.config.Timeout.Duration())
|
||||
if err != nil {
|
||||
return nil, false, false, err
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||
Metadata: exporterMetadata,
|
||||
Network: p.config.Network,
|
||||
NetworkProjectId: builderProjectId,
|
||||
RawStateTimeout: "5m",
|
||||
StateTimeout: "5m",
|
||||
SourceImageFamily: "debian-9-worker",
|
||||
SourceImageProjectId: "compute-image-tools",
|
||||
Subnetwork: p.config.Subnetwork,
|
||||
@ -149,7 +149,6 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
},
|
||||
}
|
||||
exporterConfig.CalcTimeout()
|
||||
|
||||
driver, err := googlecompute.NewDriverGCE(ui, builderProjectId,
|
||||
p.config.account, p.config.VaultGCPOauthEngine)
|
||||
|
@ -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 time.Duration `mapstructure:"start_retry_timeout"`
|
||||
StartRetryTimeout config.DurationString `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 == 0 {
|
||||
p.config.StartRetryTimeout = 5 * time.Minute
|
||||
if p.config.StartRetryTimeout == "" {
|
||||
p.config.StartRetryTimeout = "5m"
|
||||
}
|
||||
|
||||
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}.Run(ctx, func(ctx context.Context) error {
|
||||
err = retry.Config{StartTimeout: p.config.StartRetryTimeout.Duration()}.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}.Run(ctx, func(context.Context) error {
|
||||
err = retry.Config{StartTimeout: p.config.StartRetryTimeout.Duration()}.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)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
@ -510,7 +509,7 @@ func TestProvisionerProvision_UploadFails(t *testing.T) {
|
||||
p := new(Provisioner)
|
||||
comm := new(packer.ScriptUploadErrorMockCommunicator)
|
||||
p.Prepare(config)
|
||||
p.config.StartRetryTimeout = time.Second
|
||||
p.config.StartRetryTimeout = "1s"
|
||||
err := p.Provision(context.Background(), ui, comm)
|
||||
if !strings.Contains(err.Error(), packer.ScriptUploadErrorMockCommunicatorError.Error()) {
|
||||
t.Fatalf("expected Provision() error %q to contain %q",
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
type Provisioner struct {
|
||||
Duration time.Duration
|
||||
Duration config.DurationString
|
||||
}
|
||||
|
||||
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):
|
||||
case <-time.After(p.Duration.Duration()):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
)
|
||||
|
||||
func test1sConfig() map[string]interface{} {
|
||||
@ -20,7 +22,7 @@ func TestConfigPrepare_1s(t *testing.T) {
|
||||
t.Fatalf("prerare failed: %v", err)
|
||||
}
|
||||
|
||||
if p.Duration != time.Second {
|
||||
if p.Duration.Duration() != time.Second {
|
||||
t.Fatal("wrong duration")
|
||||
}
|
||||
}
|
||||
@ -29,7 +31,7 @@ func TestProvisioner_Provision(t *testing.T) {
|
||||
ctxCancelled, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
type fields struct {
|
||||
Duration time.Duration
|
||||
Duration config.DurationString
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@ -40,8 +42,8 @@ func TestProvisioner_Provision(t *testing.T) {
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"valid sleep", fields{time.Millisecond}, args{context.Background()}, false},
|
||||
{"timeout", fields{time.Millisecond}, args{ctxCancelled}, true},
|
||||
{"valid sleep", fields{"1ms"}, args{context.Background()}, false},
|
||||
{"timeout", fields{"1ms"}, args{ctxCancelled}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -44,7 +44,7 @@ type Config struct {
|
||||
RestartCheckCommand string `mapstructure:"restart_check_command"`
|
||||
|
||||
// The timeout for waiting for the machine to restart
|
||||
RestartTimeout time.Duration `mapstructure:"restart_timeout"`
|
||||
RestartTimeout config.DurationString `mapstructure:"restart_timeout"`
|
||||
|
||||
// Whether to check the registry (see RegistryKeys) for pending reboots
|
||||
CheckKey bool `mapstructure:"check_registry"`
|
||||
@ -85,8 +85,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
p.config.RestartCheckCommand = DefaultRestartCheckCommand
|
||||
}
|
||||
|
||||
if p.config.RestartTimeout == 0 {
|
||||
p.config.RestartTimeout = 5 * time.Minute
|
||||
if p.config.RestartTimeout == "" {
|
||||
p.config.RestartTimeout = "5m"
|
||||
}
|
||||
if err := p.config.RestartTimeout.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(p.config.RegistryKeys) == 0 {
|
||||
@ -107,7 +110,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}.Run(ctx, func(context.Context) error {
|
||||
err := retry.Config{StartTimeout: p.config.RestartTimeout.Duration()}.Run(ctx, func(context.Context) error {
|
||||
cmd = &packer.RemoteCmd{Command: command}
|
||||
return cmd.RunWithUi(ctx, comm, ui)
|
||||
})
|
||||
@ -127,7 +130,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)
|
||||
timeout := time.After(p.config.RestartTimeout.Duration())
|
||||
var err error
|
||||
|
||||
p.comm = comm
|
||||
|
@ -31,7 +31,7 @@ func TestProvisionerPrepare_Defaults(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if p.config.RestartTimeout != 5*time.Minute {
|
||||
if p.config.RestartTimeout.Duration() != 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 != 1*time.Minute {
|
||||
if p.config.RestartTimeout.Duration() != 1*time.Minute {
|
||||
t.Errorf("unexpected restart timeout: %s", p.config.RestartTimeout)
|
||||
}
|
||||
}
|
||||
|
@ -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 time.Duration `mapstructure:"start_retry_timeout"`
|
||||
StartRetryTimeout config.DurationString `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 == 0 {
|
||||
p.config.StartRetryTimeout = 5 * time.Minute
|
||||
if p.config.StartRetryTimeout == "" {
|
||||
p.config.StartRetryTimeout = "5m"
|
||||
}
|
||||
|
||||
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}.Run(ctx, func(ctx context.Context) error {
|
||||
err = retry.Config{StartTimeout: p.config.StartRetryTimeout.Duration()}.Run(ctx, func(ctx context.Context) error {
|
||||
if _, err := f.Seek(0, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ func (r *rawTemplate) decoder(
|
||||
result interface{},
|
||||
md *mapstructure.Metadata) *mapstructure.Decoder {
|
||||
d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
|
||||
DecodeHook: nil,
|
||||
Metadata: md,
|
||||
Result: result,
|
||||
})
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
@ -99,7 +98,7 @@ func TestParse(t *testing.T) {
|
||||
Provisioners: []*Provisioner{
|
||||
{
|
||||
Type: "something",
|
||||
PauseBefore: 1 * time.Second,
|
||||
PauseBefore: "1s",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -112,7 +111,7 @@ func TestParse(t *testing.T) {
|
||||
Provisioners: []*Provisioner{
|
||||
{
|
||||
Type: "something",
|
||||
Timeout: 5 * time.Minute,
|
||||
Timeout: "5m",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -358,6 +357,12 @@ func TestParse(t *testing.T) {
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
"parse-bad-prov-timeout.json",
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
"parse-comment.json",
|
||||
&Template{
|
||||
|
@ -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 time.Duration `mapstructure:"pause_before" json:"pause_before,omitempty"`
|
||||
Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"`
|
||||
PauseBefore config.DurationString `mapstructure:"pause_before" json:"pause_before,omitempty"`
|
||||
Timeout config.DurationString `mapstructure:"timeout" json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON conducts the necessary flattening of the Provisioner struct
|
||||
|
11
template/test-fixtures/parse-bad-prov-timeout.json
Normal file
11
template/test-fixtures/parse-bad-prov-timeout.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"builders": [{
|
||||
"type": "foo"
|
||||
}],
|
||||
|
||||
"provisioners": [{
|
||||
"timeout": 555,
|
||||
"type": "bar",
|
||||
"only": ["foo"]
|
||||
}]
|
||||
}
|
@ -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` (time.Duration) - 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
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
"managed_image_name": "TargetImageName",
|
||||
"managed_image_resource_group_name": "TargetResourceGroup"
|
||||
|
||||
- `shared_image_gallery_timeout` (time.Duration) - 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` (time.Duration) - 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:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user