add aws_polling config option to override env variables
This commit is contained in:
parent
89d57b8635
commit
788dc32598
|
@ -398,12 +398,15 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
GeneratedData: generatedData,
|
||||
},
|
||||
&StepCreateVolume{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
RootVolumeType: b.config.RootVolumeType,
|
||||
RootVolumeSize: b.config.RootVolumeSize,
|
||||
RootVolumeTags: b.config.RootVolumeTags,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
&StepAttachVolume{},
|
||||
&StepAttachVolume{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&StepEarlyUnflock{},
|
||||
&chroot.StepPreMountCommands{
|
||||
Commands: b.config.PreMountCommands,
|
||||
|
@ -427,7 +430,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
},
|
||||
&chroot.StepChrootProvision{},
|
||||
&chroot.StepEarlyCleanup{},
|
||||
&StepSnapshot{},
|
||||
&StepSnapshot{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&awscommon.StepDeregisterAMI{
|
||||
AccessConfig: &b.config.AccessConfig,
|
||||
ForceDeregister: b.config.AMIForceDeregister,
|
||||
|
@ -440,6 +445,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
|
||||
EnableAMIENASupport: b.config.AMIENASupport,
|
||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&awscommon.StepAMIRegionCopy{
|
||||
AccessConfig: &b.config.AccessConfig,
|
||||
|
|
|
@ -52,6 +52,7 @@ type FlatConfig struct {
|
|||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" hcl2-schema-generator:"ami_block_device_mappings,direct" required:"false" cty:"ami_block_device_mappings" hcl:"ami_block_device_mappings"`
|
||||
ChrootMounts [][]string `mapstructure:"chroot_mounts" required:"false" cty:"chroot_mounts" hcl:"chroot_mounts"`
|
||||
CommandWrapper *string `mapstructure:"command_wrapper" required:"false" cty:"command_wrapper" hcl:"command_wrapper"`
|
||||
|
@ -127,6 +128,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
|
||||
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
|
||||
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
|
||||
"chroot_mounts": &hcldec.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.List(cty.String)), Required: false},
|
||||
"command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false},
|
||||
|
|
|
@ -19,8 +19,9 @@ import (
|
|||
// device string - The location where the volume was attached.
|
||||
// attach_cleanup CleanupFunc
|
||||
type StepAttachVolume struct {
|
||||
attached bool
|
||||
volumeId string
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
attached bool
|
||||
volumeId string
|
||||
}
|
||||
|
||||
func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
|
@ -51,7 +52,7 @@ func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) mu
|
|||
s.volumeId = volumeId
|
||||
|
||||
// Wait for the volume to become attached
|
||||
err = awscommon.WaitUntilVolumeAttached(ctx, ec2conn, s.volumeId)
|
||||
err = s.PollingConfig.WaitUntilVolumeAttached(ctx, ec2conn, s.volumeId)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error waiting for volume: %s", err)
|
||||
state.Put("error", err)
|
||||
|
@ -87,7 +88,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
|
|||
s.attached = false
|
||||
|
||||
// Wait for the volume to detach
|
||||
err = awscommon.WaitUntilVolumeDetached(aws.BackgroundContext(), ec2conn, s.volumeId)
|
||||
err = s.PollingConfig.WaitUntilVolumeDetached(aws.BackgroundContext(), ec2conn, s.volumeId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error waiting for volume: %s", err)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
// Produces:
|
||||
// volume_id string - The ID of the created volume
|
||||
type StepCreateVolume struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
volumeId string
|
||||
RootVolumeSize int64
|
||||
RootVolumeType string
|
||||
|
@ -110,7 +111,7 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu
|
|||
log.Printf("Volume ID: %s", s.volumeId)
|
||||
|
||||
// Wait for the volume to become ready
|
||||
err = awscommon.WaitUntilVolumeAvailable(ctx, ec2conn, s.volumeId)
|
||||
err = s.PollingConfig.WaitUntilVolumeAvailable(ctx, ec2conn, s.volumeId)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error waiting for volume: %s", err)
|
||||
state.Put("error", err)
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
// StepRegisterAMI creates the AMI.
|
||||
type StepRegisterAMI struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
RootVolumeSize int64
|
||||
EnableAMIENASupport confighelper.Trilean
|
||||
EnableAMISriovNetSupport bool
|
||||
|
@ -81,7 +82,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
state.Put("amis", amis)
|
||||
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
|
||||
if err := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -16,7 +16,8 @@ import (
|
|||
// Produces:
|
||||
// snapshot_id string - ID of the created snapshot
|
||||
type StepSnapshot struct {
|
||||
snapshotId string
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
snapshotId string
|
||||
}
|
||||
|
||||
func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
|
@ -43,7 +44,7 @@ func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multis
|
|||
ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
|
||||
|
||||
// Wait for the snapshot to be ready
|
||||
err = awscommon.WaitUntilSnapshotDone(ctx, ec2conn, s.snapshotId)
|
||||
err = s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, s.snapshotId)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error waiting for snapshot: %s", err)
|
||||
state.Put("error", err)
|
||||
|
|
|
@ -138,6 +138,9 @@ type AccessConfig struct {
|
|||
// }
|
||||
// ```
|
||||
VaultAWSEngine VaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false"`
|
||||
// [Polling configuration](#polling-configuration) for the AWS waiter. Configures the waiter that checks
|
||||
// resource state.
|
||||
PollingConfig *AWSPollingConfig `mapstructure:"aws_polling" required:"false"`
|
||||
|
||||
getEC2Connection func() ec2iface.EC2API
|
||||
}
|
||||
|
@ -215,7 +218,6 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
|||
if c.DecodeAuthZMessages {
|
||||
DecodeAuthZMessages(c.session)
|
||||
}
|
||||
LogEnvOverrideWarnings()
|
||||
|
||||
return c.session, nil
|
||||
}
|
||||
|
@ -296,6 +298,11 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
|||
fmt.Errorf("`access_key` and `secret_key` must both be either set or not set."))
|
||||
}
|
||||
|
||||
if c.PollingConfig == nil {
|
||||
c.PollingConfig = new(AWSPollingConfig)
|
||||
}
|
||||
c.PollingConfig.LogEnvOverrideWarnings()
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ func testAccessConfig() *AccessConfig {
|
|||
getEC2Connection: func() ec2iface.EC2API {
|
||||
return &mockEC2Client{}
|
||||
},
|
||||
PollingConfig: new(AWSPollingConfig),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type AWSPollingConfig
|
||||
package common
|
||||
|
||||
import (
|
||||
|
@ -38,12 +40,45 @@ type StateChangeConf struct {
|
|||
// Following are wrapper functions that use Packer's environment-variables to
|
||||
// determine retry logic, then call the AWS SDK's built-in waiters.
|
||||
|
||||
func WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.EC2API, imageId string) error {
|
||||
// Polling configuration for the AWS waiter. Configures the waiter for resources creation or actions like attaching
|
||||
// volumes or importing image.
|
||||
// Usage example:
|
||||
//
|
||||
// In JSON:
|
||||
// ```json
|
||||
// "aws_polling" : {
|
||||
// "delay_seconds": 30,
|
||||
// "max_attempts": 50
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// In HCL2:
|
||||
// ```hcl
|
||||
// aws_polling {
|
||||
// delay_seconds = 30
|
||||
// max_attempts = 50
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
type AWSPollingConfig struct {
|
||||
// Specifies the maximum number of attempts the waiter will check for resource state.
|
||||
// This value can also be set via the AWS_MAX_ATTEMPTS.
|
||||
// If both option and environment variable are set, the max_attepmts will be considered over the AWS_MAX_ATTEMPTS.
|
||||
// If none is set, defaults to AWS waiter default which is 40.
|
||||
MaxAttempts int `mapstructure:"max_attempts" required:"false"`
|
||||
// Specifies the delay in seconds between attempts to check the resource state.
|
||||
// This value can also be set via the AWS_POLL_DELAY_SECONDS.
|
||||
// If both option and environment variable are set, the delay_seconds will be considered over the AWS_POLL_DELAY_SECONDS.
|
||||
// If none is set, defaults to AWS waiter default which is 15 seconds.
|
||||
DelaySeconds int `mapstructure:"delay_seconds" required:"false"`
|
||||
}
|
||||
|
||||
func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.EC2API, imageId string) error {
|
||||
imageInput := ec2.DescribeImagesInput{
|
||||
ImageIds: []*string{&imageId},
|
||||
}
|
||||
|
||||
waitOpts := getWaiterOptions()
|
||||
waitOpts := w.getWaiterOptions()
|
||||
if len(waitOpts) == 0 {
|
||||
// Bump this default to 30 minutes because the aws default
|
||||
// of ten minutes doesn't work for some of our long-running copies.
|
||||
|
@ -66,7 +101,7 @@ func WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.EC2API, imageId string
|
|||
return err
|
||||
}
|
||||
|
||||
func WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
|
||||
|
||||
instanceInput := ec2.DescribeInstancesInput{
|
||||
InstanceIds: []*string{&instanceId},
|
||||
|
@ -75,12 +110,11 @@ func WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.EC2, instanceId string)
|
|||
err := conn.WaitUntilInstanceRunningWithContext(
|
||||
ctx,
|
||||
&instanceInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
func WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
|
||||
|
||||
func (w *AWSPollingConfig) WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
|
||||
instanceInput := ec2.DescribeInstancesInput{
|
||||
InstanceIds: []*string{&instanceId},
|
||||
}
|
||||
|
@ -88,12 +122,12 @@ func WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId stri
|
|||
err := conn.WaitUntilInstanceTerminatedWithContext(
|
||||
ctx,
|
||||
&instanceInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
// This function works for both requesting and cancelling spot instances.
|
||||
func WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId string) error {
|
||||
spotRequestInput := ec2.DescribeSpotInstanceRequestsInput{
|
||||
SpotInstanceRequestIds: []*string{&spotRequestId},
|
||||
}
|
||||
|
@ -101,11 +135,11 @@ func WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId
|
|||
err := conn.WaitUntilSpotInstanceRequestFulfilledWithContext(
|
||||
ctx,
|
||||
&spotRequestInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
func WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
|
||||
volumeInput := ec2.DescribeVolumesInput{
|
||||
VolumeIds: []*string{&volumeId},
|
||||
}
|
||||
|
@ -113,11 +147,11 @@ func WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) e
|
|||
err := conn.WaitUntilVolumeAvailableWithContext(
|
||||
ctx,
|
||||
&volumeInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
func WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2, snapshotID string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2, snapshotID string) error {
|
||||
snapInput := ec2.DescribeSnapshotsInput{
|
||||
SnapshotIds: []*string{&snapshotID},
|
||||
}
|
||||
|
@ -125,13 +159,13 @@ func WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2, snapshotID string) er
|
|||
err := conn.WaitUntilSnapshotCompletedWithContext(
|
||||
ctx,
|
||||
&snapInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Wrappers for our custom AWS waiters
|
||||
|
||||
func WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
|
||||
volumeInput := ec2.DescribeVolumesInput{
|
||||
VolumeIds: []*string{&volumeId},
|
||||
}
|
||||
|
@ -139,11 +173,11 @@ func WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) er
|
|||
err := WaitForVolumeToBeAttached(conn,
|
||||
ctx,
|
||||
&volumeInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
func WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
|
||||
volumeInput := ec2.DescribeVolumesInput{
|
||||
VolumeIds: []*string{&volumeId},
|
||||
}
|
||||
|
@ -151,11 +185,11 @@ func WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) er
|
|||
err := WaitForVolumeToBeDetached(conn,
|
||||
ctx,
|
||||
&volumeInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
func WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error {
|
||||
func (w *AWSPollingConfig) WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error {
|
||||
importInput := ec2.DescribeImportImageTasksInput{
|
||||
ImportTaskIds: []*string{&taskID},
|
||||
}
|
||||
|
@ -163,7 +197,7 @@ func WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error
|
|||
err := WaitForImageToBeImported(conn,
|
||||
ctx,
|
||||
&importInput,
|
||||
getWaiterOptions()...)
|
||||
w.getWaiterOptions()...)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -298,8 +332,18 @@ type overridableWaitVars struct {
|
|||
awsTimeoutSeconds envInfo
|
||||
}
|
||||
|
||||
func getWaiterOptions() []request.WaiterOption {
|
||||
func (w *AWSPollingConfig) getWaiterOptions() []request.WaiterOption {
|
||||
envOverrides := getEnvOverrides()
|
||||
|
||||
if w.MaxAttempts != 0 {
|
||||
envOverrides.awsMaxAttempts.Val = w.MaxAttempts
|
||||
envOverrides.awsMaxAttempts.overridden = true
|
||||
}
|
||||
if w.DelaySeconds != 0 {
|
||||
envOverrides.awsPollDelaySeconds.Val = w.DelaySeconds
|
||||
envOverrides.awsPollDelaySeconds.overridden = true
|
||||
}
|
||||
|
||||
waitOpts := applyEnvOverrides(envOverrides)
|
||||
return waitOpts
|
||||
}
|
||||
|
@ -333,33 +377,38 @@ func getEnvOverrides() overridableWaitVars {
|
|||
return envValues
|
||||
}
|
||||
|
||||
func LogEnvOverrideWarnings() {
|
||||
pollDelay := os.Getenv("AWS_POLL_DELAY_SECONDS")
|
||||
timeoutSeconds := os.Getenv("AWS_TIMEOUT_SECONDS")
|
||||
maxAttempts := os.Getenv("AWS_MAX_ATTEMPTS")
|
||||
func (w *AWSPollingConfig) LogEnvOverrideWarnings() {
|
||||
pollDelayEnv := os.Getenv("AWS_POLL_DELAY_SECONDS")
|
||||
timeoutSecondsEnv := os.Getenv("AWS_TIMEOUT_SECONDS")
|
||||
maxAttemptsEnv := os.Getenv("AWS_MAX_ATTEMPTS")
|
||||
|
||||
if maxAttempts != "" && timeoutSeconds != "" {
|
||||
maxAttemptsIsSet := maxAttemptsEnv != "" || w.MaxAttempts != 0
|
||||
timeoutSecondsIsSet := timeoutSecondsEnv != ""
|
||||
pollDelayIsSet := pollDelayEnv != "" || w.DelaySeconds != 0
|
||||
|
||||
if maxAttemptsIsSet && timeoutSecondsIsSet {
|
||||
warning := fmt.Sprintf("[WARNING] (aws): AWS_MAX_ATTEMPTS and " +
|
||||
"AWS_TIMEOUT_SECONDS are both set. Packer will use " +
|
||||
"AWS_MAX_ATTEMPTS and discard AWS_TIMEOUT_SECONDS.")
|
||||
if pollDelay == "" {
|
||||
if !pollDelayIsSet {
|
||||
warning = fmt.Sprintf("%s Since you have not set the poll delay, "+
|
||||
"Packer will default to a 2-second delay.", warning)
|
||||
}
|
||||
log.Printf(warning)
|
||||
} else if timeoutSeconds != "" {
|
||||
} else if timeoutSecondsIsSet {
|
||||
log.Printf("[WARNING] (aws): env var AWS_TIMEOUT_SECONDS is " +
|
||||
"deprecated in favor of AWS_MAX_ATTEMPTS. If you have not " +
|
||||
"explicitly set AWS_POLL_DELAY_SECONDS, we are defaulting to a " +
|
||||
"poll delay of 2 seconds, regardless of the AWS waiter's default.")
|
||||
"deprecated in favor of AWS_MAX_ATTEMPTS env or aws_polling_max_attempts config option. " +
|
||||
"If you have not explicitly set AWS_POLL_DELAY_SECONDS env or aws_polling_delay_seconds config option, " +
|
||||
"we are defaulting to a poll delay of 2 seconds, regardless of the AWS waiter's default.")
|
||||
}
|
||||
if maxAttempts == "" && timeoutSeconds == "" && pollDelay == "" {
|
||||
if !maxAttemptsIsSet && !timeoutSecondsIsSet && !pollDelayIsSet {
|
||||
log.Printf("[INFO] (aws): No AWS timeout and polling overrides have been set. " +
|
||||
"Packer will default to waiter-specific delays and timeouts. If you would " +
|
||||
"like to customize the length of time between retries and max " +
|
||||
"number of retries you may do so by setting the environment " +
|
||||
"variables AWS_POLL_DELAY_SECONDS and AWS_MAX_ATTEMPTS to your " +
|
||||
"desired values.")
|
||||
"variables AWS_POLL_DELAY_SECONDS and AWS_MAX_ATTEMPTS or the " +
|
||||
"configuration options aws_polling_delay_seconds and aws_polling_max_attempts " +
|
||||
"to your desired values.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type AWSPollingConfig"; DO NOT EDIT.
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatAWSPollingConfig is an auto-generated flat version of AWSPollingConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatAWSPollingConfig struct {
|
||||
MaxAttempts *int `mapstructure:"max_attempts" required:"false" cty:"max_attempts" hcl:"max_attempts"`
|
||||
DelaySeconds *int `mapstructure:"delay_seconds" required:"false" cty:"delay_seconds" hcl:"delay_seconds"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatAWSPollingConfig.
|
||||
// FlatAWSPollingConfig is an auto-generated flat version of AWSPollingConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*AWSPollingConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatAWSPollingConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a AWSPollingConfig.
|
||||
// This spec is used by HCL to read the fields of AWSPollingConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatAWSPollingConfig.
|
||||
func (*FlatAWSPollingConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"max_attempts": &hcldec.AttrSpec{Name: "max_attempts", Type: cty.Number, Required: false},
|
||||
"delay_seconds": &hcldec.AttrSpec{Name: "delay_seconds", Type: cty.Number, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
|
@ -209,7 +209,7 @@ func (s *StepAMIRegionCopy) amiRegionCopy(ctx context.Context, state multistep.S
|
|||
}
|
||||
|
||||
// Wait for the image to become ready
|
||||
if err := WaitUntilAMIAvailable(ctx, regionconn, *resp.ImageId); err != nil {
|
||||
if err := s.AccessConfig.PollingConfig.WaitUntilAMIAvailable(ctx, regionconn, *resp.ImageId); err != nil {
|
||||
return "", snapshotIds, fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
|
||||
*resp.ImageId, target, err)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
)
|
||||
|
||||
type StepRunSourceInstance struct {
|
||||
PollingConfig *AWSPollingConfig
|
||||
AssociatePublicIpAddress bool
|
||||
LaunchMappings EC2BlockDeviceMappingsBuilder
|
||||
Comm *communicator.Config
|
||||
|
@ -234,7 +235,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
|||
InstanceIds: []*string{aws.String(instanceId)},
|
||||
}
|
||||
|
||||
if err := WaitUntilInstanceRunning(ctx, ec2conn, instanceId); err != nil {
|
||||
if err := s.PollingConfig.WaitUntilInstanceRunning(ctx, ec2conn, instanceId); err != nil {
|
||||
err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", instanceId, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
@ -364,7 +365,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
|
||||
if err := s.PollingConfig.WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ type EC2BlockDeviceMappingsBuilder interface {
|
|||
}
|
||||
|
||||
type StepRunSpotInstance struct {
|
||||
PollingConfig *AWSPollingConfig
|
||||
AssociatePublicIpAddress bool
|
||||
LaunchMappings EC2BlockDeviceMappingsBuilder
|
||||
BlockDurationMinutes int64
|
||||
|
@ -466,7 +467,7 @@ func (s *StepRunSpotInstance) Cleanup(state multistep.StateBag) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
|
||||
if err := s.PollingConfig.WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ func tStateSpot() multistep.StateBag {
|
|||
|
||||
func getBasicStep() *StepRunSpotInstance {
|
||||
stepRunSpotInstance := StepRunSpotInstance{
|
||||
PollingConfig: new(AWSPollingConfig),
|
||||
AssociatePublicIpAddress: false,
|
||||
LaunchMappings: BlockDevices{},
|
||||
BlockDurationMinutes: 0,
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
)
|
||||
|
||||
type StepStopEBSBackedInstance struct {
|
||||
PollingConfig *AWSPollingConfig
|
||||
Skip bool
|
||||
DisableStopInstance bool
|
||||
}
|
||||
|
@ -74,7 +75,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta
|
|||
&ec2.DescribeInstancesInput{
|
||||
InstanceIds: []*string{instance.InstanceId},
|
||||
},
|
||||
getWaiterOptions()...)
|
||||
s.PollingConfig.getWaiterOptions()...)
|
||||
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error waiting for instance to stop: %s", err)
|
||||
|
|
|
@ -169,6 +169,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
if b.config.IsSpotInstance() {
|
||||
instanceStep = &awscommon.StepRunSpotInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||
|
@ -191,6 +192,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
} else {
|
||||
instanceStep = &awscommon.StepRunSourceInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
|
@ -292,6 +294,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Comm: &b.config.RunConfig.Comm,
|
||||
},
|
||||
&awscommon.StepStopEBSBackedInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
Skip: b.config.IsSpotInstance(),
|
||||
DisableStopInstance: b.config.DisableStopInstance,
|
||||
},
|
||||
|
@ -308,6 +311,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
},
|
||||
&stepCreateAMI{
|
||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&awscommon.StepAMIRegionCopy{
|
||||
AccessConfig: &b.config.AccessConfig,
|
||||
|
|
|
@ -31,6 +31,7 @@ type FlatConfig struct {
|
|||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name" hcl:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description" hcl:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"`
|
||||
|
@ -171,6 +172,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
|
||||
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
|
||||
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
|
||||
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
|
||||
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
)
|
||||
|
||||
type stepCreateAMI struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
image *ec2.Image
|
||||
AMISkipBuildRegion bool
|
||||
}
|
||||
|
@ -85,8 +86,7 @@ func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
|
||||
// Wait for the image to become ready
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
|
||||
if waitErr := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *createResp.ImageId); waitErr != nil {
|
||||
if waitErr := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *createResp.ImageId); waitErr != nil {
|
||||
// waitErr should get bubbled up if the issue is a wait timeout
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", waitErr)
|
||||
imResp, imerr := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{createResp.ImageId}})
|
||||
|
|
|
@ -192,6 +192,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
if b.config.IsSpotInstance() {
|
||||
instanceStep = &awscommon.StepRunSpotInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||
|
@ -213,6 +214,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
} else {
|
||||
instanceStep = &awscommon.StepRunSourceInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
|
@ -316,6 +318,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Comm: &b.config.RunConfig.Comm,
|
||||
},
|
||||
&awscommon.StepStopEBSBackedInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
Skip: b.config.IsSpotInstance(),
|
||||
DisableStopInstance: b.config.DisableStopInstance,
|
||||
},
|
||||
|
@ -325,6 +328,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
EnableAMIENASupport: b.config.AMIENASupport,
|
||||
},
|
||||
&StepSnapshotVolumes{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
LaunchDevices: launchDevices,
|
||||
SnapshotOmitMap: b.config.LaunchMappings.GetOmissions(),
|
||||
},
|
||||
|
@ -344,6 +348,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Architecture: b.config.Architecture,
|
||||
LaunchOmitMap: b.config.LaunchMappings.GetOmissions(),
|
||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&awscommon.StepAMIRegionCopy{
|
||||
AccessConfig: &b.config.AccessConfig,
|
||||
|
|
|
@ -74,6 +74,7 @@ type FlatConfig struct {
|
|||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone" hcl:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"`
|
||||
|
@ -215,6 +216,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
|
||||
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
|
||||
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
|
||||
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
|
||||
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
// StepRegisterAMI creates the AMI.
|
||||
type StepRegisterAMI struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
RootDevice RootBlockDevice
|
||||
AMIDevices []*ec2.BlockDeviceMapping
|
||||
LaunchDevices []*ec2.BlockDeviceMapping
|
||||
|
@ -86,7 +87,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
|
||||
// Wait for the image to become ready
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
|
||||
if err := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer/builder/amazon/common"
|
||||
)
|
||||
|
||||
const sourceDeviceName = "/dev/xvdf"
|
||||
|
@ -23,6 +24,7 @@ func newStepRegisterAMI(amiDevices, launchDevices []*ec2.BlockDeviceMapping) *St
|
|||
},
|
||||
AMIDevices: amiDevices,
|
||||
LaunchDevices: launchDevices,
|
||||
PollingConfig: new(common.AWSPollingConfig),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
// Produces:
|
||||
// snapshot_ids map[string]string - IDs of the created snapshots
|
||||
type StepSnapshotVolumes struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
LaunchDevices []*ec2.BlockDeviceMapping
|
||||
snapshotIds map[string]string
|
||||
snapshotMutex sync.Mutex
|
||||
|
@ -56,7 +57,7 @@ func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName str
|
|||
s.snapshotMutex.Unlock()
|
||||
|
||||
// Wait for snapshot to be created
|
||||
err = awscommon.WaitUntilSnapshotDone(ctx, ec2conn, *createSnapResp.SnapshotId)
|
||||
err = s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, *createSnapResp.SnapshotId)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -173,6 +173,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
if b.config.IsSpotInstance() {
|
||||
instanceStep = &awscommon.StepRunSpotInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.launchBlockDevices,
|
||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||
|
@ -194,6 +195,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
} else {
|
||||
instanceStep = &awscommon.StepRunSourceInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.launchBlockDevices,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
|
@ -286,6 +288,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Comm: &b.config.RunConfig.Comm,
|
||||
},
|
||||
&awscommon.StepStopEBSBackedInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
Skip: b.config.IsSpotInstance(),
|
||||
DisableStopInstance: b.config.DisableStopInstance,
|
||||
},
|
||||
|
|
|
@ -76,6 +76,7 @@ type FlatConfig struct {
|
|||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone" hcl:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"`
|
||||
|
@ -195,6 +196,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
|
||||
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
|
||||
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
|
||||
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
|
||||
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
|
||||
|
|
|
@ -255,6 +255,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
if b.config.IsSpotInstance() {
|
||||
instanceStep = &awscommon.StepRunSpotInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||
|
@ -273,6 +274,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
} else {
|
||||
instanceStep = &awscommon.StepRunSourceInstance{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
|
@ -385,6 +387,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
|
||||
EnableAMIENASupport: b.config.AMIENASupport,
|
||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&awscommon.StepAMIRegionCopy{
|
||||
AccessConfig: &b.config.AccessConfig,
|
||||
|
|
|
@ -31,6 +31,7 @@ type FlatConfig struct {
|
|||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name" hcl:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description" hcl:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"`
|
||||
|
@ -177,6 +178,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
|
||||
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
|
||||
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
|
||||
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
|
||||
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
)
|
||||
|
||||
type StepRegisterAMI struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
EnableAMIENASupport confighelper.Trilean
|
||||
EnableAMISriovNetSupport bool
|
||||
AMISkipBuildRegion bool
|
||||
|
@ -80,7 +81,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
|
||||
// Wait for the image to become ready
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
|
||||
if err := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -119,7 +119,10 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
|||
if len(errs.Errors) > 0 {
|
||||
return errs
|
||||
}
|
||||
awscommon.LogEnvOverrideWarnings()
|
||||
if p.config.PollingConfig == nil {
|
||||
p.config.PollingConfig = new(awscommon.AWSPollingConfig)
|
||||
}
|
||||
p.config.PollingConfig.LogEnvOverrideWarnings()
|
||||
|
||||
packer.LogSecretFilter.Set(p.config.AccessKey, p.config.SecretKey, p.config.Token)
|
||||
log.Println(p.config)
|
||||
|
@ -250,7 +253,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
|||
|
||||
// Wait for import process to complete, this takes a while
|
||||
ui.Message(fmt.Sprintf("Waiting for task %s to complete (may take a while)", *import_start.ImportTaskId))
|
||||
err = awscommon.WaitUntilImageImported(aws.BackgroundContext(), ec2conn, *import_start.ImportTaskId)
|
||||
err = p.config.PollingConfig.WaitUntilImageImported(aws.BackgroundContext(), ec2conn, *import_start.ImportTaskId)
|
||||
if err != nil {
|
||||
|
||||
// Retrieve the status message
|
||||
|
@ -313,7 +316,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
|||
|
||||
ui.Message(fmt.Sprintf("Waiting for AMI rename to complete (may take a while)"))
|
||||
|
||||
if err := awscommon.WaitUntilAMIAvailable(aws.BackgroundContext(), ec2conn, *resp.ImageId); err != nil {
|
||||
if err := p.config.PollingConfig.WaitUntilAMIAvailable(aws.BackgroundContext(), ec2conn, *resp.ImageId); err != nil {
|
||||
return nil, false, false, fmt.Errorf("Error waiting for AMI (%s): %s", *resp.ImageId, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ type FlatConfig struct {
|
|||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
|
||||
S3Bucket *string `mapstructure:"s3_bucket_name" cty:"s3_bucket_name" hcl:"s3_bucket_name"`
|
||||
S3Key *string `mapstructure:"s3_key_name" cty:"s3_key_name" hcl:"s3_key_name"`
|
||||
S3Encryption *string `mapstructure:"s3_encryption" cty:"s3_encryption" hcl:"s3_encryption"`
|
||||
|
@ -79,6 +80,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
|
||||
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
|
||||
"s3_bucket_name": &hcldec.AttrSpec{Name: "s3_bucket_name", Type: cty.String, Required: false},
|
||||
"s3_key_name": &hcldec.AttrSpec{Name: "s3_key_name", Type: cty.String, Required: false},
|
||||
"s3_encryption": &hcldec.AttrSpec{Name: "s3_encryption", Type: cty.String, Required: false},
|
||||
|
|
|
@ -106,6 +106,12 @@ Block devices can be nested in the
|
|||
|
||||
@include 'builder/amazon/common/AccessConfig-not-required.mdx'
|
||||
|
||||
### Polling Configuration
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig.mdx'
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig-not-required.mdx'
|
||||
|
||||
## Basic Example
|
||||
|
||||
Here is a basic example. It is completely valid except for the access keys:
|
||||
|
|
|
@ -69,6 +69,12 @@ necessary for this build to succeed and can be found further down the page.
|
|||
|
||||
@include 'builder/amazon/common/AccessConfig-not-required.mdx'
|
||||
|
||||
### Polling Configuration
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig.mdx'
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig-not-required.mdx'
|
||||
|
||||
### Run Configuration
|
||||
|
||||
#### Required:
|
||||
|
|
|
@ -65,6 +65,12 @@ necessary for this build to succeed and can be found further down the page.
|
|||
|
||||
@include 'builder/amazon/common/AccessConfig-not-required.mdx'
|
||||
|
||||
### Polling Configuration
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig.mdx'
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig-not-required.mdx'
|
||||
|
||||
### Run Configuration
|
||||
|
||||
#### Required:
|
||||
|
|
|
@ -57,6 +57,12 @@ necessary for this build to succeed and can be found further down the page.
|
|||
|
||||
@include 'builder/amazon/common/AccessConfig-not-required.mdx'
|
||||
|
||||
### Polling Configuration
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig.mdx'
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig-not-required.mdx'
|
||||
|
||||
### AMI Configuration
|
||||
|
||||
#### Optional:
|
||||
|
|
|
@ -85,6 +85,12 @@ necessary for this build to succeed and can be found further down the page.
|
|||
|
||||
@include 'builder/amazon/common/AccessConfig-not-required.mdx'
|
||||
|
||||
### Polling Configuration
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig.mdx'
|
||||
|
||||
@include 'builder/amazon/common/AWSPollingConfig-not-required.mdx'
|
||||
|
||||
### Run Configuration
|
||||
|
||||
#### Required:
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Code generated from the comments of the AWSPollingConfig struct in builder/amazon/common/state.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
- `max_attempts` (int) - Specifies the maximum number of attempts the waiter will check for resource state.
|
||||
This value can also be set via the AWS_MAX_ATTEMPTS.
|
||||
If both option and environment variable are set, the max_attepmts will be considered over the AWS_MAX_ATTEMPTS.
|
||||
If none is set, defaults to AWS waiter default which is 40.
|
||||
|
||||
- `delay_seconds` (int) - Specifies the delay in seconds between attempts to check the resource state.
|
||||
This value can also be set via the AWS_POLL_DELAY_SECONDS.
|
||||
If both option and environment variable are set, the delay_seconds will be considered over the AWS_POLL_DELAY_SECONDS.
|
||||
If none is set, defaults to AWS waiter default which is 15 seconds.
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Code generated from the comments of the AWSPollingConfig struct in builder/amazon/common/state.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
Polling configuration for the AWS waiter. Configures the waiter for resources creation or actions like attaching
|
||||
volumes or importing image.
|
||||
Usage example:
|
||||
|
||||
In JSON:
|
||||
```json
|
||||
"aws_polling" : {
|
||||
"delay_seconds": 30,
|
||||
"max_attempts": 50
|
||||
}
|
||||
```
|
||||
|
||||
In HCL2:
|
||||
```hcl
|
||||
aws_polling {
|
||||
delay_seconds = 30
|
||||
max_attempts = 50
|
||||
}
|
||||
```
|
|
@ -81,3 +81,6 @@
|
|||
ttl = "3600s"
|
||||
}
|
||||
```
|
||||
|
||||
- `aws_polling` (\*AWSPollingConfig) - [Polling configuration](#polling-configuration) for the AWS waiter. Configures the waiter that checks
|
||||
resource state.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<!-- Code generated from the comments of the StateChangeConf struct in builder/amazon/common/state.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
StateChangeConf is the configuration struct used for `WaitForState`.
|
Loading…
Reference in New Issue