Merge pull request #9777 from hashicorp/fix_9756
Add aws_polling config option to override env variables
This commit is contained in:
commit
d74b47b734
|
@ -398,12 +398,15 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
GeneratedData: generatedData,
|
GeneratedData: generatedData,
|
||||||
},
|
},
|
||||||
&StepCreateVolume{
|
&StepCreateVolume{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
RootVolumeType: b.config.RootVolumeType,
|
RootVolumeType: b.config.RootVolumeType,
|
||||||
RootVolumeSize: b.config.RootVolumeSize,
|
RootVolumeSize: b.config.RootVolumeSize,
|
||||||
RootVolumeTags: b.config.RootVolumeTags,
|
RootVolumeTags: b.config.RootVolumeTags,
|
||||||
Ctx: b.config.ctx,
|
Ctx: b.config.ctx,
|
||||||
},
|
},
|
||||||
&StepAttachVolume{},
|
&StepAttachVolume{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
|
},
|
||||||
&StepEarlyUnflock{},
|
&StepEarlyUnflock{},
|
||||||
&chroot.StepPreMountCommands{
|
&chroot.StepPreMountCommands{
|
||||||
Commands: b.config.PreMountCommands,
|
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.StepChrootProvision{},
|
||||||
&chroot.StepEarlyCleanup{},
|
&chroot.StepEarlyCleanup{},
|
||||||
&StepSnapshot{},
|
&StepSnapshot{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
|
},
|
||||||
&awscommon.StepDeregisterAMI{
|
&awscommon.StepDeregisterAMI{
|
||||||
AccessConfig: &b.config.AccessConfig,
|
AccessConfig: &b.config.AccessConfig,
|
||||||
ForceDeregister: b.config.AMIForceDeregister,
|
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,
|
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
|
||||||
EnableAMIENASupport: b.config.AMIENASupport,
|
EnableAMIENASupport: b.config.AMIENASupport,
|
||||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
},
|
},
|
||||||
&awscommon.StepAMIRegionCopy{
|
&awscommon.StepAMIRegionCopy{
|
||||||
AccessConfig: &b.config.AccessConfig,
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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},
|
"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},
|
"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())},
|
"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())},
|
"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},
|
"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},
|
"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.
|
// device string - The location where the volume was attached.
|
||||||
// attach_cleanup CleanupFunc
|
// attach_cleanup CleanupFunc
|
||||||
type StepAttachVolume struct {
|
type StepAttachVolume struct {
|
||||||
attached bool
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
volumeId string
|
attached bool
|
||||||
|
volumeId string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
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
|
s.volumeId = volumeId
|
||||||
|
|
||||||
// Wait for the volume to become attached
|
// 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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error waiting for volume: %s", err)
|
err := fmt.Errorf("Error waiting for volume: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -87,7 +88,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
|
||||||
s.attached = false
|
s.attached = false
|
||||||
|
|
||||||
// Wait for the volume to detach
|
// 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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Error waiting for volume: %s", err)
|
return fmt.Errorf("Error waiting for volume: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
// Produces:
|
// Produces:
|
||||||
// volume_id string - The ID of the created volume
|
// volume_id string - The ID of the created volume
|
||||||
type StepCreateVolume struct {
|
type StepCreateVolume struct {
|
||||||
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
volumeId string
|
volumeId string
|
||||||
RootVolumeSize int64
|
RootVolumeSize int64
|
||||||
RootVolumeType string
|
RootVolumeType string
|
||||||
|
@ -110,7 +111,7 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu
|
||||||
log.Printf("Volume ID: %s", s.volumeId)
|
log.Printf("Volume ID: %s", s.volumeId)
|
||||||
|
|
||||||
// Wait for the volume to become ready
|
// 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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error waiting for volume: %s", err)
|
err := fmt.Errorf("Error waiting for volume: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
// StepRegisterAMI creates the AMI.
|
// StepRegisterAMI creates the AMI.
|
||||||
type StepRegisterAMI struct {
|
type StepRegisterAMI struct {
|
||||||
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
RootVolumeSize int64
|
RootVolumeSize int64
|
||||||
EnableAMIENASupport confighelper.Trilean
|
EnableAMIENASupport confighelper.Trilean
|
||||||
EnableAMISriovNetSupport bool
|
EnableAMISriovNetSupport bool
|
||||||
|
@ -81,7 +82,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
|
||||||
state.Put("amis", amis)
|
state.Put("amis", amis)
|
||||||
|
|
||||||
ui.Say("Waiting for AMI 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)
|
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
|
|
@ -16,7 +16,8 @@ import (
|
||||||
// Produces:
|
// Produces:
|
||||||
// snapshot_id string - ID of the created snapshot
|
// snapshot_id string - ID of the created snapshot
|
||||||
type StepSnapshot struct {
|
type StepSnapshot struct {
|
||||||
snapshotId string
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
|
snapshotId string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
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))
|
ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
|
||||||
|
|
||||||
// Wait for the snapshot to be ready
|
// 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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error waiting for snapshot: %s", err)
|
err := fmt.Errorf("Error waiting for snapshot: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -138,6 +138,9 @@ type AccessConfig struct {
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
VaultAWSEngine VaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false"`
|
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
|
getEC2Connection func() ec2iface.EC2API
|
||||||
}
|
}
|
||||||
|
@ -215,7 +218,6 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||||
if c.DecodeAuthZMessages {
|
if c.DecodeAuthZMessages {
|
||||||
DecodeAuthZMessages(c.session)
|
DecodeAuthZMessages(c.session)
|
||||||
}
|
}
|
||||||
LogEnvOverrideWarnings()
|
|
||||||
|
|
||||||
return c.session, nil
|
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."))
|
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
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ func testAccessConfig() *AccessConfig {
|
||||||
getEC2Connection: func() ec2iface.EC2API {
|
getEC2Connection: func() ec2iface.EC2API {
|
||||||
return &mockEC2Client{}
|
return &mockEC2Client{}
|
||||||
},
|
},
|
||||||
|
PollingConfig: new(AWSPollingConfig),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//go:generate struct-markdown
|
||||||
|
//go:generate mapstructure-to-hcl2 -type AWSPollingConfig
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -38,12 +40,45 @@ type StateChangeConf struct {
|
||||||
// Following are wrapper functions that use Packer's environment-variables to
|
// Following are wrapper functions that use Packer's environment-variables to
|
||||||
// determine retry logic, then call the AWS SDK's built-in waiters.
|
// 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_attempts will be considered over the AWS_MAX_ATTEMPTS.
|
||||||
|
// If none is set, defaults to AWS waiter default which is 40 max_attempts.
|
||||||
|
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{
|
imageInput := ec2.DescribeImagesInput{
|
||||||
ImageIds: []*string{&imageId},
|
ImageIds: []*string{&imageId},
|
||||||
}
|
}
|
||||||
|
|
||||||
waitOpts := getWaiterOptions()
|
waitOpts := w.getWaiterOptions()
|
||||||
if len(waitOpts) == 0 {
|
if len(waitOpts) == 0 {
|
||||||
// Bump this default to 30 minutes because the aws default
|
// Bump this default to 30 minutes because the aws default
|
||||||
// of ten minutes doesn't work for some of our long-running copies.
|
// 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
|
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{
|
instanceInput := ec2.DescribeInstancesInput{
|
||||||
InstanceIds: []*string{&instanceId},
|
InstanceIds: []*string{&instanceId},
|
||||||
|
@ -75,12 +110,11 @@ func WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.EC2, instanceId string)
|
||||||
err := conn.WaitUntilInstanceRunningWithContext(
|
err := conn.WaitUntilInstanceRunningWithContext(
|
||||||
ctx,
|
ctx,
|
||||||
&instanceInput,
|
&instanceInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
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{
|
instanceInput := ec2.DescribeInstancesInput{
|
||||||
InstanceIds: []*string{&instanceId},
|
InstanceIds: []*string{&instanceId},
|
||||||
}
|
}
|
||||||
|
@ -88,12 +122,12 @@ func WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId stri
|
||||||
err := conn.WaitUntilInstanceTerminatedWithContext(
|
err := conn.WaitUntilInstanceTerminatedWithContext(
|
||||||
ctx,
|
ctx,
|
||||||
&instanceInput,
|
&instanceInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function works for both requesting and cancelling spot instances.
|
// 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{
|
spotRequestInput := ec2.DescribeSpotInstanceRequestsInput{
|
||||||
SpotInstanceRequestIds: []*string{&spotRequestId},
|
SpotInstanceRequestIds: []*string{&spotRequestId},
|
||||||
}
|
}
|
||||||
|
@ -101,11 +135,11 @@ func WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId
|
||||||
err := conn.WaitUntilSpotInstanceRequestFulfilledWithContext(
|
err := conn.WaitUntilSpotInstanceRequestFulfilledWithContext(
|
||||||
ctx,
|
ctx,
|
||||||
&spotRequestInput,
|
&spotRequestInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
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{
|
volumeInput := ec2.DescribeVolumesInput{
|
||||||
VolumeIds: []*string{&volumeId},
|
VolumeIds: []*string{&volumeId},
|
||||||
}
|
}
|
||||||
|
@ -113,11 +147,11 @@ func WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) e
|
||||||
err := conn.WaitUntilVolumeAvailableWithContext(
|
err := conn.WaitUntilVolumeAvailableWithContext(
|
||||||
ctx,
|
ctx,
|
||||||
&volumeInput,
|
&volumeInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
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{
|
snapInput := ec2.DescribeSnapshotsInput{
|
||||||
SnapshotIds: []*string{&snapshotID},
|
SnapshotIds: []*string{&snapshotID},
|
||||||
}
|
}
|
||||||
|
@ -125,13 +159,13 @@ func WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2, snapshotID string) er
|
||||||
err := conn.WaitUntilSnapshotCompletedWithContext(
|
err := conn.WaitUntilSnapshotCompletedWithContext(
|
||||||
ctx,
|
ctx,
|
||||||
&snapInput,
|
&snapInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrappers for our custom AWS waiters
|
// 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{
|
volumeInput := ec2.DescribeVolumesInput{
|
||||||
VolumeIds: []*string{&volumeId},
|
VolumeIds: []*string{&volumeId},
|
||||||
}
|
}
|
||||||
|
@ -139,11 +173,11 @@ func WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) er
|
||||||
err := WaitForVolumeToBeAttached(conn,
|
err := WaitForVolumeToBeAttached(conn,
|
||||||
ctx,
|
ctx,
|
||||||
&volumeInput,
|
&volumeInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
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{
|
volumeInput := ec2.DescribeVolumesInput{
|
||||||
VolumeIds: []*string{&volumeId},
|
VolumeIds: []*string{&volumeId},
|
||||||
}
|
}
|
||||||
|
@ -151,11 +185,11 @@ func WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) er
|
||||||
err := WaitForVolumeToBeDetached(conn,
|
err := WaitForVolumeToBeDetached(conn,
|
||||||
ctx,
|
ctx,
|
||||||
&volumeInput,
|
&volumeInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
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{
|
importInput := ec2.DescribeImportImageTasksInput{
|
||||||
ImportTaskIds: []*string{&taskID},
|
ImportTaskIds: []*string{&taskID},
|
||||||
}
|
}
|
||||||
|
@ -163,7 +197,7 @@ func WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error
|
||||||
err := WaitForImageToBeImported(conn,
|
err := WaitForImageToBeImported(conn,
|
||||||
ctx,
|
ctx,
|
||||||
&importInput,
|
&importInput,
|
||||||
getWaiterOptions()...)
|
w.getWaiterOptions()...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,8 +332,18 @@ type overridableWaitVars struct {
|
||||||
awsTimeoutSeconds envInfo
|
awsTimeoutSeconds envInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWaiterOptions() []request.WaiterOption {
|
func (w *AWSPollingConfig) getWaiterOptions() []request.WaiterOption {
|
||||||
envOverrides := getEnvOverrides()
|
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)
|
waitOpts := applyEnvOverrides(envOverrides)
|
||||||
return waitOpts
|
return waitOpts
|
||||||
}
|
}
|
||||||
|
@ -333,33 +377,38 @@ func getEnvOverrides() overridableWaitVars {
|
||||||
return envValues
|
return envValues
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogEnvOverrideWarnings() {
|
func (w *AWSPollingConfig) LogEnvOverrideWarnings() {
|
||||||
pollDelay := os.Getenv("AWS_POLL_DELAY_SECONDS")
|
pollDelayEnv := os.Getenv("AWS_POLL_DELAY_SECONDS")
|
||||||
timeoutSeconds := os.Getenv("AWS_TIMEOUT_SECONDS")
|
timeoutSecondsEnv := os.Getenv("AWS_TIMEOUT_SECONDS")
|
||||||
maxAttempts := os.Getenv("AWS_MAX_ATTEMPTS")
|
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 " +
|
warning := fmt.Sprintf("[WARNING] (aws): AWS_MAX_ATTEMPTS and " +
|
||||||
"AWS_TIMEOUT_SECONDS are both set. Packer will use " +
|
"AWS_TIMEOUT_SECONDS are both set. Packer will use " +
|
||||||
"AWS_MAX_ATTEMPTS and discard AWS_TIMEOUT_SECONDS.")
|
"AWS_MAX_ATTEMPTS and discard AWS_TIMEOUT_SECONDS.")
|
||||||
if pollDelay == "" {
|
if !pollDelayIsSet {
|
||||||
warning = fmt.Sprintf("%s Since you have not set the poll delay, "+
|
warning = fmt.Sprintf("%s Since you have not set the poll delay, "+
|
||||||
"Packer will default to a 2-second delay.", warning)
|
"Packer will default to a 2-second delay.", warning)
|
||||||
}
|
}
|
||||||
log.Printf(warning)
|
log.Printf(warning)
|
||||||
} else if timeoutSeconds != "" {
|
} else if timeoutSecondsIsSet {
|
||||||
log.Printf("[WARNING] (aws): env var AWS_TIMEOUT_SECONDS is " +
|
log.Printf("[WARNING] (aws): env var AWS_TIMEOUT_SECONDS is " +
|
||||||
"deprecated in favor of AWS_MAX_ATTEMPTS. If you have not " +
|
"deprecated in favor of AWS_MAX_ATTEMPTS env or aws_polling_max_attempts config option. " +
|
||||||
"explicitly set AWS_POLL_DELAY_SECONDS, we are defaulting to a " +
|
"If you have not explicitly set AWS_POLL_DELAY_SECONDS env or aws_polling_delay_seconds config option, " +
|
||||||
"poll delay of 2 seconds, regardless of the AWS waiter's default.")
|
"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. " +
|
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 " +
|
"Packer will default to waiter-specific delays and timeouts. If you would " +
|
||||||
"like to customize the length of time between retries and max " +
|
"like to customize the length of time between retries and max " +
|
||||||
"number of retries you may do so by setting the environment " +
|
"number of retries you may do so by setting the environment " +
|
||||||
"variables AWS_POLL_DELAY_SECONDS and AWS_MAX_ATTEMPTS to your " +
|
"variables AWS_POLL_DELAY_SECONDS and AWS_MAX_ATTEMPTS or the " +
|
||||||
"desired values.")
|
"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
|
// 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",
|
return "", snapshotIds, fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
|
||||||
*resp.ImageId, target, err)
|
*resp.ImageId, target, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepRunSourceInstance struct {
|
type StepRunSourceInstance struct {
|
||||||
|
PollingConfig *AWSPollingConfig
|
||||||
AssociatePublicIpAddress bool
|
AssociatePublicIpAddress bool
|
||||||
LaunchMappings EC2BlockDeviceMappingsBuilder
|
LaunchMappings EC2BlockDeviceMappingsBuilder
|
||||||
Comm *communicator.Config
|
Comm *communicator.Config
|
||||||
|
@ -234,7 +235,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
||||||
InstanceIds: []*string{aws.String(instanceId)},
|
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)
|
err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", instanceId, err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
@ -364,7 +365,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
|
||||||
return
|
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())
|
ui.Error(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ type EC2BlockDeviceMappingsBuilder interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type StepRunSpotInstance struct {
|
type StepRunSpotInstance struct {
|
||||||
|
PollingConfig *AWSPollingConfig
|
||||||
AssociatePublicIpAddress bool
|
AssociatePublicIpAddress bool
|
||||||
LaunchMappings EC2BlockDeviceMappingsBuilder
|
LaunchMappings EC2BlockDeviceMappingsBuilder
|
||||||
BlockDurationMinutes int64
|
BlockDurationMinutes int64
|
||||||
|
@ -466,7 +467,7 @@ func (s *StepRunSpotInstance) Cleanup(state multistep.StateBag) {
|
||||||
return
|
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())
|
ui.Error(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ func tStateSpot() multistep.StateBag {
|
||||||
|
|
||||||
func getBasicStep() *StepRunSpotInstance {
|
func getBasicStep() *StepRunSpotInstance {
|
||||||
stepRunSpotInstance := StepRunSpotInstance{
|
stepRunSpotInstance := StepRunSpotInstance{
|
||||||
|
PollingConfig: new(AWSPollingConfig),
|
||||||
AssociatePublicIpAddress: false,
|
AssociatePublicIpAddress: false,
|
||||||
LaunchMappings: BlockDevices{},
|
LaunchMappings: BlockDevices{},
|
||||||
BlockDurationMinutes: 0,
|
BlockDurationMinutes: 0,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepStopEBSBackedInstance struct {
|
type StepStopEBSBackedInstance struct {
|
||||||
|
PollingConfig *AWSPollingConfig
|
||||||
Skip bool
|
Skip bool
|
||||||
DisableStopInstance bool
|
DisableStopInstance bool
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta
|
||||||
&ec2.DescribeInstancesInput{
|
&ec2.DescribeInstancesInput{
|
||||||
InstanceIds: []*string{instance.InstanceId},
|
InstanceIds: []*string{instance.InstanceId},
|
||||||
},
|
},
|
||||||
getWaiterOptions()...)
|
s.PollingConfig.getWaiterOptions()...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error waiting for instance to stop: %s", err)
|
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() {
|
if b.config.IsSpotInstance() {
|
||||||
instanceStep = &awscommon.StepRunSpotInstance{
|
instanceStep = &awscommon.StepRunSpotInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.LaunchMappings,
|
LaunchMappings: b.config.LaunchMappings,
|
||||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||||
|
@ -191,6 +192,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instanceStep = &awscommon.StepRunSourceInstance{
|
instanceStep = &awscommon.StepRunSourceInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.LaunchMappings,
|
LaunchMappings: b.config.LaunchMappings,
|
||||||
Comm: &b.config.RunConfig.Comm,
|
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,
|
Comm: &b.config.RunConfig.Comm,
|
||||||
},
|
},
|
||||||
&awscommon.StepStopEBSBackedInstance{
|
&awscommon.StepStopEBSBackedInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
Skip: b.config.IsSpotInstance(),
|
Skip: b.config.IsSpotInstance(),
|
||||||
DisableStopInstance: b.config.DisableStopInstance,
|
DisableStopInstance: b.config.DisableStopInstance,
|
||||||
},
|
},
|
||||||
|
@ -308,6 +311,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
},
|
},
|
||||||
&stepCreateAMI{
|
&stepCreateAMI{
|
||||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
},
|
},
|
||||||
&awscommon.StepAMIRegionCopy{
|
&awscommon.StepAMIRegionCopy{
|
||||||
AccessConfig: &b.config.AccessConfig,
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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},
|
"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},
|
"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())},
|
"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_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
|
||||||
"ami_description": &hcldec.AttrSpec{Name: "ami_description", 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},
|
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepCreateAMI struct {
|
type stepCreateAMI struct {
|
||||||
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
image *ec2.Image
|
image *ec2.Image
|
||||||
AMISkipBuildRegion bool
|
AMISkipBuildRegion bool
|
||||||
}
|
}
|
||||||
|
@ -85,8 +86,7 @@ func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi
|
||||||
|
|
||||||
// Wait for the image to become ready
|
// Wait for the image to become ready
|
||||||
ui.Say("Waiting for AMI to become ready...")
|
ui.Say("Waiting for AMI to become ready...")
|
||||||
|
if waitErr := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *createResp.ImageId); waitErr != nil {
|
||||||
if waitErr := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *createResp.ImageId); waitErr != nil {
|
|
||||||
// waitErr should get bubbled up if the issue is a wait timeout
|
// waitErr should get bubbled up if the issue is a wait timeout
|
||||||
err := fmt.Errorf("Error waiting for AMI: %s", waitErr)
|
err := fmt.Errorf("Error waiting for AMI: %s", waitErr)
|
||||||
imResp, imerr := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{createResp.ImageId}})
|
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() {
|
if b.config.IsSpotInstance() {
|
||||||
instanceStep = &awscommon.StepRunSpotInstance{
|
instanceStep = &awscommon.StepRunSpotInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.LaunchMappings,
|
LaunchMappings: b.config.LaunchMappings,
|
||||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||||
|
@ -213,6 +214,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instanceStep = &awscommon.StepRunSourceInstance{
|
instanceStep = &awscommon.StepRunSourceInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.LaunchMappings,
|
LaunchMappings: b.config.LaunchMappings,
|
||||||
Comm: &b.config.RunConfig.Comm,
|
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,
|
Comm: &b.config.RunConfig.Comm,
|
||||||
},
|
},
|
||||||
&awscommon.StepStopEBSBackedInstance{
|
&awscommon.StepStopEBSBackedInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
Skip: b.config.IsSpotInstance(),
|
Skip: b.config.IsSpotInstance(),
|
||||||
DisableStopInstance: b.config.DisableStopInstance,
|
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,
|
EnableAMIENASupport: b.config.AMIENASupport,
|
||||||
},
|
},
|
||||||
&StepSnapshotVolumes{
|
&StepSnapshotVolumes{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
LaunchDevices: launchDevices,
|
LaunchDevices: launchDevices,
|
||||||
SnapshotOmitMap: b.config.LaunchMappings.GetOmissions(),
|
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,
|
Architecture: b.config.Architecture,
|
||||||
LaunchOmitMap: b.config.LaunchMappings.GetOmissions(),
|
LaunchOmitMap: b.config.LaunchMappings.GetOmissions(),
|
||||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
},
|
},
|
||||||
&awscommon.StepAMIRegionCopy{
|
&awscommon.StepAMIRegionCopy{
|
||||||
AccessConfig: &b.config.AccessConfig,
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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},
|
"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},
|
"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())},
|
"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},
|
"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},
|
"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},
|
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
// StepRegisterAMI creates the AMI.
|
// StepRegisterAMI creates the AMI.
|
||||||
type StepRegisterAMI struct {
|
type StepRegisterAMI struct {
|
||||||
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
RootDevice RootBlockDevice
|
RootDevice RootBlockDevice
|
||||||
AMIDevices []*ec2.BlockDeviceMapping
|
AMIDevices []*ec2.BlockDeviceMapping
|
||||||
LaunchDevices []*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
|
// Wait for the image to become ready
|
||||||
ui.Say("Waiting for AMI 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)
|
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/service/ec2"
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/hashicorp/packer/builder/amazon/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sourceDeviceName = "/dev/xvdf"
|
const sourceDeviceName = "/dev/xvdf"
|
||||||
|
@ -23,6 +24,7 @@ func newStepRegisterAMI(amiDevices, launchDevices []*ec2.BlockDeviceMapping) *St
|
||||||
},
|
},
|
||||||
AMIDevices: amiDevices,
|
AMIDevices: amiDevices,
|
||||||
LaunchDevices: launchDevices,
|
LaunchDevices: launchDevices,
|
||||||
|
PollingConfig: new(common.AWSPollingConfig),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
// Produces:
|
// Produces:
|
||||||
// snapshot_ids map[string]string - IDs of the created snapshots
|
// snapshot_ids map[string]string - IDs of the created snapshots
|
||||||
type StepSnapshotVolumes struct {
|
type StepSnapshotVolumes struct {
|
||||||
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
LaunchDevices []*ec2.BlockDeviceMapping
|
LaunchDevices []*ec2.BlockDeviceMapping
|
||||||
snapshotIds map[string]string
|
snapshotIds map[string]string
|
||||||
snapshotMutex sync.Mutex
|
snapshotMutex sync.Mutex
|
||||||
|
@ -56,7 +57,7 @@ func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName str
|
||||||
s.snapshotMutex.Unlock()
|
s.snapshotMutex.Unlock()
|
||||||
|
|
||||||
// Wait for snapshot to be created
|
// Wait for snapshot to be created
|
||||||
err = awscommon.WaitUntilSnapshotDone(ctx, ec2conn, *createSnapResp.SnapshotId)
|
err = s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, *createSnapResp.SnapshotId)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
|
|
||||||
if b.config.IsSpotInstance() {
|
if b.config.IsSpotInstance() {
|
||||||
instanceStep = &awscommon.StepRunSpotInstance{
|
instanceStep = &awscommon.StepRunSpotInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.launchBlockDevices,
|
LaunchMappings: b.config.launchBlockDevices,
|
||||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||||
|
@ -194,6 +195,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instanceStep = &awscommon.StepRunSourceInstance{
|
instanceStep = &awscommon.StepRunSourceInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.launchBlockDevices,
|
LaunchMappings: b.config.launchBlockDevices,
|
||||||
Comm: &b.config.RunConfig.Comm,
|
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,
|
Comm: &b.config.RunConfig.Comm,
|
||||||
},
|
},
|
||||||
&awscommon.StepStopEBSBackedInstance{
|
&awscommon.StepStopEBSBackedInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
Skip: b.config.IsSpotInstance(),
|
Skip: b.config.IsSpotInstance(),
|
||||||
DisableStopInstance: b.config.DisableStopInstance,
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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},
|
"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},
|
"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())},
|
"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},
|
"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},
|
"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},
|
"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() {
|
if b.config.IsSpotInstance() {
|
||||||
instanceStep = &awscommon.StepRunSpotInstance{
|
instanceStep = &awscommon.StepRunSpotInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.LaunchMappings,
|
LaunchMappings: b.config.LaunchMappings,
|
||||||
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
BlockDurationMinutes: b.config.BlockDurationMinutes,
|
||||||
|
@ -273,6 +274,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instanceStep = &awscommon.StepRunSourceInstance{
|
instanceStep = &awscommon.StepRunSourceInstance{
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||||
LaunchMappings: b.config.LaunchMappings,
|
LaunchMappings: b.config.LaunchMappings,
|
||||||
Comm: &b.config.RunConfig.Comm,
|
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,
|
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
|
||||||
EnableAMIENASupport: b.config.AMIENASupport,
|
EnableAMIENASupport: b.config.AMIENASupport,
|
||||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||||
|
PollingConfig: b.config.PollingConfig,
|
||||||
},
|
},
|
||||||
&awscommon.StepAMIRegionCopy{
|
&awscommon.StepAMIRegionCopy{
|
||||||
AccessConfig: &b.config.AccessConfig,
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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},
|
"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},
|
"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())},
|
"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_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
|
||||||
"ami_description": &hcldec.AttrSpec{Name: "ami_description", 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},
|
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepRegisterAMI struct {
|
type StepRegisterAMI struct {
|
||||||
|
PollingConfig *awscommon.AWSPollingConfig
|
||||||
EnableAMIENASupport confighelper.Trilean
|
EnableAMIENASupport confighelper.Trilean
|
||||||
EnableAMISriovNetSupport bool
|
EnableAMISriovNetSupport bool
|
||||||
AMISkipBuildRegion 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
|
// Wait for the image to become ready
|
||||||
ui.Say("Waiting for AMI 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)
|
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
|
|
@ -119,7 +119,10 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||||
if len(errs.Errors) > 0 {
|
if len(errs.Errors) > 0 {
|
||||||
return errs
|
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)
|
packer.LogSecretFilter.Set(p.config.AccessKey, p.config.SecretKey, p.config.Token)
|
||||||
log.Println(p.config)
|
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
|
// 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))
|
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 {
|
if err != nil {
|
||||||
|
|
||||||
// Retrieve the status message
|
// 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)"))
|
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)
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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},
|
"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},
|
"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())},
|
"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_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_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},
|
"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'
|
@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
|
## Basic Example
|
||||||
|
|
||||||
Here is a basic example. It is completely valid except for the access keys:
|
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'
|
@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
|
### Run Configuration
|
||||||
|
|
||||||
#### Required:
|
#### 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'
|
@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
|
### Run Configuration
|
||||||
|
|
||||||
#### Required:
|
#### 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'
|
@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
|
### AMI Configuration
|
||||||
|
|
||||||
#### Optional:
|
#### 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'
|
@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
|
### Run Configuration
|
||||||
|
|
||||||
#### Required:
|
#### 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_attempts will be considered over the AWS_MAX_ATTEMPTS.
|
||||||
|
If none is set, defaults to AWS waiter default which is 40 max_attempts.
|
||||||
|
|
||||||
|
- `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"
|
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