From b7ef757e0d2f4ecb96f25a3180c3bad894c7c530 Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Wed, 13 May 2026 15:50:28 +0200 Subject: [PATCH 1/8] feat: Use AWS SDK v2 only --- builder/chroot/builder.go | 33 +- builder/chroot/step_attach_volume.go | 23 +- builder/chroot/step_check_root_device.go | 6 +- builder/chroot/step_create_volume.go | 65 +- builder/chroot/step_create_volume_test.go | 30 +- builder/chroot/step_instance_info.go | 24 +- builder/chroot/step_mount_device.go | 8 +- builder/chroot/step_register_ami.go | 51 +- builder/chroot/step_register_ami_test.go | 43 +- builder/chroot/step_snapshot.go | 16 +- builder/common/access_config.go | 194 +--- builder/common/access_config_test.go | 32 +- builder/common/ami_config.go | 10 +- builder/common/ami_config_test.go | 12 +- builder/common/ami_filter.go | 23 +- builder/common/artifact.go | 21 +- builder/common/block_device.go | 36 +- builder/common/block_device_test.go | 136 +-- builder/common/boot_mode_validation.go | 10 +- builder/common/boot_mode_validation_test.go | 8 +- builder/common/build_filter.go | 12 +- builder/common/build_filter_test.go | 6 +- builder/common/helper_funcs.go | 15 +- builder/common/interpolate_build_info.go | 18 +- builder/common/regions.go | 13 +- builder/common/run_config.go | 30 +- builder/common/run_config_test.go | 11 +- builder/common/ssh.go | 18 +- builder/common/ssh_test.go | 18 +- builder/common/ssm/session.go | 36 +- builder/common/state.go | 842 +++++++++++++----- builder/common/step_ami_region_copy.go | 108 +-- builder/common/step_ami_region_copy_test.go | 75 +- builder/common/step_create_ssm_tunnel.go | 35 +- builder/common/step_create_tags.go | 30 +- builder/common/step_deregister_ami.go | 44 +- builder/common/step_enable_deprecation.go | 4 +- builder/common/step_key_pair.go | 4 +- builder/common/step_key_pair_test.go | 6 +- builder/common/step_modify_ami_attributes.go | 11 +- builder/common/step_modify_ebs_instance.go | 4 +- builder/common/step_network_info.go | 57 +- builder/common/step_network_info_test.go | 4 +- builder/common/step_pre_validate.go | 4 +- builder/common/step_pre_validate_test.go | 14 +- builder/common/step_run_source_instance.go | 161 ++-- builder/common/step_run_spot_instance.go | 184 ++-- builder/common/step_run_spot_instance_test.go | 84 +- builder/common/step_source_ami_info.go | 25 +- builder/common/tags.go | 30 +- builder/common/test_helper_funcs.go | 16 +- builder/ebs/step_enable_fast_launch.go | 2 +- builder/instance/builder.go | 36 +- builder/instance/step_register_ami.go | 19 +- builder/instance/step_upload_bundle.go | 7 +- common/clients/ec2_client.go | 2 + common/step_run_spot_instance_test.go | 2 +- go.mod | 194 ++-- go.sum | 553 ++++++------ 59 files changed, 1917 insertions(+), 1598 deletions(-) diff --git a/builder/chroot/builder.go b/builder/chroot/builder.go index 66772f50..93152a92 100644 --- a/builder/chroot/builder.go +++ b/builder/chroot/builder.go @@ -16,7 +16,8 @@ import ( "fmt" "runtime" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/hcl/v2/hcldec" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" "github.com/hashicorp/packer-plugin-sdk/chroot" @@ -112,12 +113,12 @@ type Config struct { // The size of the root volume in GB for the chroot environment and the // resulting AMI. Default size is the snapshot size of the source_ami // unless from_scratch is true, in which case this field must be defined. - RootVolumeSize int64 `mapstructure:"root_volume_size" required:"false"` + RootVolumeSize int32 `mapstructure:"root_volume_size" required:"false"` // The type of EBS volume for the chroot environment and resulting AMI. The // default value is the type of the source_ami, unless from_scratch is // true, in which case the default value is gp2. You can only specify io1 // if building based on top of a source_ami which is also io1. - RootVolumeType string `mapstructure:"root_volume_type" required:"false"` + RootVolumeType ec2types.VolumeType `mapstructure:"root_volume_type" required:"false"` // The source AMI whose root volume will be copied and provisioned on the // currently running instance. This must be an EBS-backed AMI with a root // volume snapshot that you have access to. Note: this is not used when @@ -196,19 +197,19 @@ type Config struct { RootVolumeKmsKeyId string `mapstructure:"root_volume_kms_key_id" required:"false"` // what architecture to use when registering the final AMI; valid options // are "arm64", "arm64_mac", "i386", "x86_64", or "x86_64_mac". Defaults to "x86_64". - Architecture string `mapstructure:"ami_architecture" required:"false"` + Architecture ec2types.ArchitectureValues `mapstructure:"ami_architecture" required:"false"` // The boot mode. Valid options are `legacy-bios` and `uefi`. See the documentation on // [boot modes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ami-boot.html) for // more information. Defaults to `legacy-bios` when `ami_architecture` is `x86_64` and // `uefi` when `ami_architecture` is `arm64`. - BootMode string `mapstructure:"boot_mode" required:"false"` + BootMode ec2types.BootModeValues `mapstructure:"boot_mode" required:"false"` // Base64 representation of the non-volatile UEFI variable store. For more information // see [AWS documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/uefi-secure-boot-optionB.html). UefiData string `mapstructure:"uefi_data" required:"false"` // NitroTPM Support. Valid options are `v2.0`. See the documentation on // [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for // more information. Only enabled if a valid option is provided, otherwise ignored. - TpmSupport string `mapstructure:"tpm_support" required:"false"` + TpmSupport ec2types.TpmSupportValues `mapstructure:"tpm_support" required:"false"` ctx interpolate.Context } @@ -370,7 +371,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { } valid := false - for _, validArch := range []string{"arm64", "arm64_mac", "i386", "x86_64", "x86_64_mac"} { + for _, validArch := range []ec2types.ArchitectureValues{ec2types.ArchitectureValuesArm64, ec2types.ArchitectureValuesArm64Mac, ec2types.ArchitectureValuesX8664, ec2types.ArchitectureValuesX8664Mac} { if validArch == b.config.Architecture { valid = true break @@ -380,8 +381,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { errs = packersdk.MultiErrorAppend(errs, errors.New(`The only valid ami_architecture values are "arm64", "arm64_mac", "i386", "x86_64", or "x86_64_mac"`)) } - if b.config.TpmSupport != "" && b.config.TpmSupport != ec2.TpmSupportValuesV20 { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`The only valid tpm_support value is %q`, ec2.TpmSupportValuesV20)) + if b.config.TpmSupport != "" && b.config.TpmSupport != ec2types.TpmSupportValuesV20 { + errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`The only valid tpm_support value is %q`, ec2types.TpmSupportValuesV20)) } if b.config.BootMode != "" { @@ -392,9 +393,9 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { } if b.config.UefiData != "" { - if b.config.BootMode == "legacy-bios" { + if b.config.BootMode == ec2types.BootModeValuesLegacyBios { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`You can't use uefi_data with boot_mode set to "legacy-bios".`)) - } else if b.config.BootMode == "" && b.config.Architecture != "arm64" { + } else if b.config.BootMode == "" && b.config.Architecture != ec2types.ArchitectureValuesArm64 { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`You need boot_mode set to "uefi" to use uefi_data, `+ `"%s" architecture defaults to "legacy-bios".`, b.config.Architecture)) } @@ -416,11 +417,11 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) return nil, errors.New("The amazon-chroot builder only works on Linux environments.") } - session, err := b.config.Session() + awscfg, err := b.config.GetAWSConfig(ctx) if err != nil { return nil, err } - ec2conn := ec2.New(session) + ec2conn := ec2.NewFromConfig(*awscfg) wrappedCommand := func(command string) (string, error) { ictx := b.config.ctx @@ -434,7 +435,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) state.Put("access_config", &b.config.AccessConfig) state.Put("ami_config", &b.config.AMIConfig) state.Put("ec2", ec2conn) - state.Put("awsSession", session) + state.Put("awsConfig", awscfg) state.Put("hook", hook) state.Put("ui", ui) state.Put("wrappedCommand", common.CommandWrapper(wrappedCommand)) @@ -529,7 +530,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) RegionKeyIds: b.config.AMIRegionKMSKeyIDs, EncryptBootVolume: b.config.AMIEncryptBootVolume, Name: b.config.AMIName, - OriginalRegion: *ec2conn.Config.Region, + OriginalRegion: awscfg.Region, AMISnapshotCopyDurationMinutes: b.config.AMISnapshotCopyDurationMinutes, }, &awscommon.StepEnableDeprecation{ @@ -578,7 +579,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) artifact := &awscommon.Artifact{ Amis: state.Get("amis").(map[string]string), BuilderIdValue: BuilderId, - Session: session, + Config: awscfg, StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, } diff --git a/builder/chroot/step_attach_volume.go b/builder/chroot/step_attach_volume.go index ab2e5e3f..49334cb7 100644 --- a/builder/chroot/step_attach_volume.go +++ b/builder/chroot/step_attach_volume.go @@ -8,9 +8,10 @@ import ( "fmt" "strings" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -29,9 +30,9 @@ type StepAttachVolume struct { } func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) device := state.Get("device").(string) - instance := state.Get("instance").(*ec2.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) volumeId := state.Get("volume_id").(string) @@ -39,7 +40,7 @@ func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) mu attachVolume := strings.Replace(device, "/xvd", "/sd", 1) ui.Say(fmt.Sprintf("Attaching the root volume to %s", attachVolume)) - _, err := ec2conn.AttachVolume(&ec2.AttachVolumeInput{ + _, err := ec2conn.AttachVolume(ctx, &ec2.AttachVolumeInput{ InstanceId: instance.InstanceId, VolumeId: &volumeId, Device: &attachVolume, @@ -64,27 +65,29 @@ func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) mu return multistep.ActionHalt } + state.Put("context", ctx) state.Put("attach_cleanup", s) return multistep.ActionContinue } func (s *StepAttachVolume) Cleanup(state multistep.StateBag) { + ctx := state.Get("context").(context.Context) ui := state.Get("ui").(packersdk.Ui) - if err := s.CleanupFunc(state); err != nil { + if err := s.CleanupFunc(ctx, state); err != nil { ui.Error(err.Error()) } } -func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error { +func (s *StepAttachVolume) CleanupFunc(ctx context.Context, state multistep.StateBag) error { if !s.attached { return nil } - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Detaching EBS volume...") - _, err := ec2conn.DetachVolume(&ec2.DetachVolumeInput{VolumeId: &s.volumeId}) + _, err := ec2conn.DetachVolume(ctx, &ec2.DetachVolumeInput{VolumeId: &s.volumeId}) if err != nil { return fmt.Errorf("Error detaching EBS volume: %s", err) } @@ -92,7 +95,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error { s.attached = false // Wait for the volume to detach - err = s.PollingConfig.WaitUntilVolumeDetached(aws.BackgroundContext(), ec2conn, s.volumeId) + err = s.PollingConfig.WaitUntilVolumeDetached(ctx, ec2conn, s.volumeId) if err != nil { return fmt.Errorf("Error waiting for volume: %s", err) } diff --git a/builder/chroot/step_check_root_device.go b/builder/chroot/step_check_root_device.go index b1aa2c23..f6e66395 100644 --- a/builder/chroot/step_check_root_device.go +++ b/builder/chroot/step_check_root_device.go @@ -7,7 +7,7 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -16,13 +16,13 @@ import ( type StepCheckRootDevice struct{} func (s *StepCheckRootDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - image := state.Get("source_image").(*ec2.Image) + image := state.Get("source_image").(*ec2types.Image) ui := state.Get("ui").(packersdk.Ui) ui.Say("Checking the root device on source AMI...") // It must be EBS-backed otherwise the build won't work - if *image.RootDeviceType != "ebs" { + if image.RootDeviceType != ec2types.DeviceTypeEbs { err := fmt.Errorf("The root device of the source AMI must be EBS-backed.") state.Put("error", err) ui.Error(err.Error()) diff --git a/builder/chroot/step_create_volume.go b/builder/chroot/step_create_volume.go index f18285c7..2317d71c 100644 --- a/builder/chroot/step_create_volume.go +++ b/builder/chroot/step_create_volume.go @@ -9,9 +9,11 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -27,8 +29,8 @@ import ( type StepCreateVolume struct { PollingConfig *awscommon.AWSPollingConfig volumeId string - RootVolumeSize int64 - RootVolumeType string + RootVolumeSize int32 + RootVolumeType ec2types.VolumeType RootVolumeTags map[string]string RootVolumeEncryptBoot config.Trilean RootVolumeKmsKeyId string @@ -37,11 +39,18 @@ type StepCreateVolume struct { func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) - ec2conn := state.Get("ec2").(*ec2.EC2) - instance := state.Get("instance").(*ec2.Instance) + ec2conn := state.Get("ec2").(clients.Ec2Client) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) - volTags, err := awscommon.TagMap(s.RootVolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + awscfg, err := config.GetAWSConfig(ctx) + if err != nil { + err := fmt.Errorf("Error getting AWS config: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + volTags, err := awscommon.TagMap(s.RootVolumeTags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { err := fmt.Errorf("Error tagging volumes: %s", err) state.Put("error", err) @@ -50,11 +59,11 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu } // Collect tags for tagging on resource creation - var tagSpecs []*ec2.TagSpecification + var tagSpecs []ec2types.TagSpecification if len(volTags) > 0 { - runVolTags := &ec2.TagSpecification{ - ResourceType: aws.String("volume"), + runVolTags := ec2types.TagSpecification{ + ResourceType: ec2types.ResourceTypeVolume, Tags: volTags, } @@ -63,8 +72,8 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu var createVolume *ec2.CreateVolumeInput if config.FromScratch { - rootVolumeType := ec2.VolumeTypeGp2 - if s.RootVolumeType == "io1" { + rootVolumeType := ec2types.VolumeTypeGp2 + if s.RootVolumeType == ec2types.VolumeTypeIo1 { err := errors.New("Cannot use io1 volume when building from scratch") state.Put("error", err) ui.Error(err.Error()) @@ -74,18 +83,18 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu } createVolume = &ec2.CreateVolumeInput{ AvailabilityZone: instance.Placement.AvailabilityZone, - Size: aws.Int64(s.RootVolumeSize), - VolumeType: aws.String(rootVolumeType), + Size: aws.Int32(s.RootVolumeSize), + VolumeType: rootVolumeType, } } else { // Determine the root device snapshot - image := state.Get("source_image").(*ec2.Image) + image := state.Get("source_image").(*ec2types.Image) log.Printf("Searching for root device of the image (%s)", *image.RootDeviceName) - var rootDevice *ec2.BlockDeviceMapping + var rootDevice *ec2types.BlockDeviceMapping for _, device := range image.BlockDeviceMappings { - if *device.DeviceName == *image.RootDeviceName { - rootDevice = device + if aws.ToString(device.DeviceName) == aws.ToString(image.RootDeviceName) { + rootDevice = &device break } } @@ -100,12 +109,12 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu } if len(tagSpecs) > 0 { - createVolume.SetTagSpecifications(tagSpecs) + createVolume.TagSpecifications = tagSpecs volTags.Report(ui) } log.Printf("Create args: %+v", createVolume) - createVolumeResp, err := ec2conn.CreateVolume(createVolume) + createVolumeResp, err := ec2conn.CreateVolume(ctx, createVolume) if err != nil { err := fmt.Errorf("Error creating root volume: %s", err) state.Put("error", err) @@ -126,6 +135,7 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu return multistep.ActionHalt } + state.Put("context", ctx) state.Put("volume_id", s.volumeId) return multistep.ActionContinue } @@ -135,17 +145,18 @@ func (s *StepCreateVolume) Cleanup(state multistep.StateBag) { return } - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Deleting the created EBS volume...") - _, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: &s.volumeId}) + ctx := state.Get("context").(context.Context) + _, err := ec2conn.DeleteVolume(ctx, &ec2.DeleteVolumeInput{VolumeId: &s.volumeId}) if err != nil { ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err)) } } -func (s *StepCreateVolume) buildCreateVolumeInput(az string, rootDevice *ec2.BlockDeviceMapping) (*ec2.CreateVolumeInput, error) { +func (s *StepCreateVolume) buildCreateVolumeInput(az string, rootDevice *ec2types.BlockDeviceMapping) (*ec2.CreateVolumeInput, error) { if rootDevice == nil { return nil, fmt.Errorf("Couldn't find root device!") } @@ -159,7 +170,7 @@ func (s *StepCreateVolume) buildCreateVolumeInput(az string, rootDevice *ec2.Blo KmsKeyId: rootDevice.Ebs.KmsKeyId, } if s.RootVolumeSize > *rootDevice.Ebs.VolumeSize { - createVolumeInput.Size = aws.Int64(s.RootVolumeSize) + createVolumeInput.Size = aws.Int32(s.RootVolumeSize) } if s.RootVolumeEncryptBoot.True() { @@ -170,15 +181,15 @@ func (s *StepCreateVolume) buildCreateVolumeInput(az string, rootDevice *ec2.Blo createVolumeInput.KmsKeyId = aws.String(s.RootVolumeKmsKeyId) } - if s.RootVolumeType == "" || s.RootVolumeType == *rootDevice.Ebs.VolumeType { + if s.RootVolumeType == "" || s.RootVolumeType == rootDevice.Ebs.VolumeType { return createVolumeInput, nil } if s.RootVolumeType == "io1" { - return nil, fmt.Errorf("Root volume type cannot be io1, because existing root volume type was %s", *rootDevice.Ebs.VolumeType) + return nil, fmt.Errorf("Root volume type cannot be io1, because existing root volume type was %s", rootDevice.Ebs.VolumeType) } - createVolumeInput.VolumeType = aws.String(s.RootVolumeType) + createVolumeInput.VolumeType = s.RootVolumeType // non io1 cannot set iops createVolumeInput.Iops = nil diff --git a/builder/chroot/step_create_volume_test.go b/builder/chroot/step_create_volume_test.go index b56fcaf1..c74e8305 100644 --- a/builder/chroot/step_create_volume_test.go +++ b/builder/chroot/step_create_volume_test.go @@ -6,18 +6,18 @@ package chroot import ( "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/stretchr/testify/assert" ) -func buildTestRootDevice() *ec2.BlockDeviceMapping { - return &ec2.BlockDeviceMapping{ - Ebs: &ec2.EbsBlockDevice{ - VolumeSize: aws.Int64(10), +func buildTestRootDevice() *ec2types.BlockDeviceMapping { + return &ec2types.BlockDeviceMapping{ + Ebs: &ec2types.EbsBlockDevice{ + VolumeSize: aws.Int32(10), SnapshotId: aws.String("snap-1234"), - VolumeType: aws.String("gp2"), + VolumeType: ec2types.VolumeTypeGp2, Encrypted: aws.Bool(false), }, } @@ -50,28 +50,28 @@ func TestCreateVolume_Expand(t *testing.T) { func TestCreateVolume_io1_to_io1(t *testing.T) { stepCreateVolume := StepCreateVolume{RootVolumeType: "io1"} testRootDevice := buildTestRootDevice() - testRootDevice.Ebs.VolumeType = aws.String("io1") - testRootDevice.Ebs.Iops = aws.Int64(1000) + testRootDevice.Ebs.VolumeType = ec2types.VolumeTypeIo1 + testRootDevice.Ebs.Iops = aws.Int32(1000) ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice) assert.NoError(t, err) - assert.Equal(t, *ret.VolumeType, stepCreateVolume.RootVolumeType) - assert.Equal(t, *ret.Iops, *testRootDevice.Ebs.Iops) + assert.Equal(t, ret.VolumeType, stepCreateVolume.RootVolumeType) + assert.Equal(t, ret.Iops, *testRootDevice.Ebs.Iops) } func TestCreateVolume_io1_to_gp2(t *testing.T) { stepCreateVolume := StepCreateVolume{RootVolumeType: "gp2"} testRootDevice := buildTestRootDevice() - testRootDevice.Ebs.VolumeType = aws.String("io1") - testRootDevice.Ebs.Iops = aws.Int64(1000) + testRootDevice.Ebs.VolumeType = ec2types.VolumeTypeIo1 + testRootDevice.Ebs.Iops = aws.Int32(1000) ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice) assert.NoError(t, err) - assert.Equal(t, *ret.VolumeType, stepCreateVolume.RootVolumeType) + assert.Equal(t, ret.VolumeType, stepCreateVolume.RootVolumeType) assert.Nil(t, ret.Iops) } func TestCreateVolume_gp2_to_io1(t *testing.T) { - stepCreateVolume := StepCreateVolume{RootVolumeType: "io1"} + stepCreateVolume := StepCreateVolume{RootVolumeType: ec2types.VolumeTypeIo1} testRootDevice := buildTestRootDevice() _, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice) diff --git a/builder/chroot/step_instance_info.go b/builder/chroot/step_instance_info.go index a782c53a..34eeda80 100644 --- a/builder/chroot/step_instance_info.go +++ b/builder/chroot/step_instance_info.go @@ -8,9 +8,9 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -19,15 +19,23 @@ import ( type StepInstanceInfo struct{} func (s *StepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) - session := state.Get("awsSession").(*session.Session) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) + config := state.Get("config").(*Config) + + awscfg, err := config.GetAWSConfig(ctx) + if err != nil { + err := fmt.Errorf("Error getting AWS config: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } // Get our own instance ID ui.Say("Gathering information about this EC2 instance...") - ec2meta := ec2metadata.New(session) - identity, err := ec2meta.GetInstanceIdentityDocument() + idmsconn := imds.NewFromConfig(*awscfg) + identity, err := idmsconn.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{}) if err != nil { err := fmt.Errorf( "Error retrieving the ID of the instance Packer is running on.\n" + @@ -39,7 +47,7 @@ func (s *StepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) mu log.Printf("Instance ID: %s", identity.InstanceID) // Query the entire instance metadata - instancesResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []*string{&identity.InstanceID}}) + instancesResp, err := ec2conn.DescribeInstances(ctx, &ec2.DescribeInstancesInput{InstanceIds: []string{identity.InstanceID}}) if err != nil { err := fmt.Errorf("Error getting instance data: %s", err) state.Put("error", err) diff --git a/builder/chroot/step_mount_device.go b/builder/chroot/step_mount_device.go index b13fa054..c82ddb31 100644 --- a/builder/chroot/step_mount_device.go +++ b/builder/chroot/step_mount_device.go @@ -12,7 +12,7 @@ import ( "path/filepath" "strings" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/common" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -48,12 +48,12 @@ func (s *StepMountDevice) Run(ctx context.Context, state multistep.StateBag) mul } wrappedCommand := state.Get("wrappedCommand").(common.CommandWrapper) - var virtualizationType string + var virtualizationType ec2types.VirtualizationType if config.FromScratch || config.AMIVirtType != "" { virtualizationType = config.AMIVirtType } else { - image := state.Get("source_image").(*ec2.Image) - virtualizationType = *image.VirtualizationType + image := state.Get("source_image").(*ec2types.Image) + virtualizationType = image.VirtualizationType log.Printf("Source image virtualization type is: %s", virtualizationType) } diff --git a/builder/chroot/step_register_ami.go b/builder/chroot/step_register_ami.go index 597d1b8f..fab02143 100644 --- a/builder/chroot/step_register_ami.go +++ b/builder/chroot/step_register_ami.go @@ -7,9 +7,11 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/random" @@ -19,20 +21,27 @@ import ( // StepRegisterAMI creates the AMI. type StepRegisterAMI struct { PollingConfig *awscommon.AWSPollingConfig - RootVolumeSize int64 + RootVolumeSize int32 EnableAMIENASupport config.Trilean EnableAMISriovNetSupport bool AMISkipBuildRegion bool - BootMode string + BootMode ec2types.BootModeValues UefiData string - TpmSupport string + TpmSupport ec2types.TpmSupportValues } func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) snapshotID := state.Get("snapshot_id").(string) ui := state.Get("ui").(packersdk.Ui) + awscfg, err := config.GetAWSConfig(ctx) + if err != nil { + err := fmt.Errorf("Error getting AWS config: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } ui.Say("Registering the AMI...") @@ -59,7 +68,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul if config.FromScratch { registerOpts = buildBaseRegisterOpts(config, nil, s.RootVolumeSize, snapshotID, amiName) } else { - image := state.Get("source_image").(*ec2.Image) + image := state.Get("source_image").(*ec2types.Image) registerOpts = buildBaseRegisterOpts(config, image, s.RootVolumeSize, snapshotID, amiName) } @@ -74,16 +83,16 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul registerOpts.EnaSupport = aws.Bool(true) } if s.BootMode != "" { - registerOpts.BootMode = aws.String(s.BootMode) + registerOpts.BootMode = s.BootMode } if s.UefiData != "" { registerOpts.UefiData = aws.String(s.UefiData) } if s.TpmSupport != "" { - registerOpts.TpmSupport = aws.String(s.TpmSupport) + registerOpts.TpmSupport = s.TpmSupport } - registerResp, err := ec2conn.RegisterImage(registerOpts) + registerResp, err := ec2conn.RegisterImage(ctx, registerOpts) if err != nil { state.Put("error", fmt.Errorf("Error registering AMI: %s", err)) ui.Error(state.Get("error").(error).Error()) @@ -93,7 +102,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul // Set the AMI ID in the state ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageId)) amis := make(map[string]string) - amis[*ec2conn.Config.Region] = *registerResp.ImageId + amis[awscfg.Region] = *registerResp.ImageId state.Put("amis", amis) ui.Say("Waiting for AMI to become ready...") @@ -110,9 +119,9 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {} // Builds the base register opts with architecture, name, root block device, mappings, virtualizationtype -func buildBaseRegisterOpts(config *Config, sourceImage *ec2.Image, rootVolumeSize int64, snapshotID string, amiName string) *ec2.RegisterImageInput { +func buildBaseRegisterOpts(config *Config, sourceImage *ec2types.Image, rootVolumeSize int32, snapshotID string, amiName string) *ec2.RegisterImageInput { var ( - mappings []*ec2.BlockDeviceMapping + mappings []ec2types.BlockDeviceMapping rootDeviceName string ) @@ -126,18 +135,18 @@ func buildBaseRegisterOpts(config *Config, sourceImage *ec2.Image, rootVolumeSiz rootDeviceName = *sourceImage.RootDeviceName } - newMappings := make([]*ec2.BlockDeviceMapping, len(mappings)) + newMappings := make([]ec2types.BlockDeviceMapping, len(mappings)) for i, device := range mappings { newDevice := device if *newDevice.DeviceName == rootDeviceName { if newDevice.Ebs != nil { newDevice.Ebs.SnapshotId = aws.String(snapshotID) } else { - newDevice.Ebs = &ec2.EbsBlockDevice{SnapshotId: aws.String(snapshotID)} + newDevice.Ebs = &ec2types.EbsBlockDevice{SnapshotId: aws.String(snapshotID)} } if generatingNewBlockDeviceMappings || rootVolumeSize > *newDevice.Ebs.VolumeSize { - newDevice.Ebs.VolumeSize = aws.Int64(rootVolumeSize) + newDevice.Ebs.VolumeSize = aws.Int32(rootVolumeSize) } } @@ -153,9 +162,9 @@ func buildBaseRegisterOpts(config *Config, sourceImage *ec2.Image, rootVolumeSiz if config.FromScratch { return &ec2.RegisterImageInput{ Name: &amiName, - Architecture: aws.String(config.Architecture), + Architecture: config.Architecture, RootDeviceName: aws.String(rootDeviceName), - VirtualizationType: aws.String(config.AMIVirtType), + VirtualizationType: aws.String(string(config.AMIVirtType)), BlockDeviceMappings: newMappings, } } @@ -163,17 +172,17 @@ func buildBaseRegisterOpts(config *Config, sourceImage *ec2.Image, rootVolumeSiz return buildRegisterOptsFromExistingImage(config, sourceImage, newMappings, rootDeviceName, amiName) } -func buildRegisterOptsFromExistingImage(config *Config, image *ec2.Image, mappings []*ec2.BlockDeviceMapping, rootDeviceName string, amiName string) *ec2.RegisterImageInput { +func buildRegisterOptsFromExistingImage(config *Config, image *ec2types.Image, mappings []ec2types.BlockDeviceMapping, rootDeviceName string, amiName string) *ec2.RegisterImageInput { registerOpts := &ec2.RegisterImageInput{ Name: &amiName, Architecture: image.Architecture, RootDeviceName: &rootDeviceName, BlockDeviceMappings: mappings, - VirtualizationType: image.VirtualizationType, + VirtualizationType: aws.String(string(image.VirtualizationType)), } if config.AMIVirtType != "" { - registerOpts.VirtualizationType = aws.String(config.AMIVirtType) + registerOpts.VirtualizationType = aws.String(string(config.AMIVirtType)) } if config.AMIVirtType != "hvm" { diff --git a/builder/chroot/step_register_ami_test.go b/builder/chroot/step_register_ami_test.go index 96d94012..e4b01c20 100644 --- a/builder/chroot/step_register_ami_test.go +++ b/builder/chroot/step_register_ami_test.go @@ -6,18 +6,17 @@ package chroot import ( "testing" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" amazon "github.com/hashicorp/packer-plugin-amazon/builder/common" "github.com/hashicorp/packer-plugin-sdk/common" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" ) -func testImage() ec2.Image { - return ec2.Image{ +func testImage() ec2types.Image { + return ec2types.Image{ ImageId: aws.String("ami-abcd1234"), Name: aws.String("ami_test_name"), - Architecture: aws.String("x86_64"), + Architecture: ec2types.ArchitectureValuesX8664, KernelId: aws.String("aki-abcd1234"), } } @@ -31,11 +30,11 @@ func TestStepRegisterAmi_buildRegisterOpts_pv(t *testing.T) { image := testImage() - blockDevices := []*ec2.BlockDeviceMapping{} + blockDevices := []ec2types.BlockDeviceMapping{} opts := buildRegisterOptsFromExistingImage(&config, &image, blockDevices, rootDeviceName, config.AMIName) - expected := config.AMIVirtType + expected := string(config.AMIVirtType) if *opts.VirtualizationType != expected { t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, *opts.VirtualizationType) } @@ -65,11 +64,11 @@ func TestStepRegisterAmi_buildRegisterOpts_hvm(t *testing.T) { image := testImage() - blockDevices := []*ec2.BlockDeviceMapping{} + blockDevices := []ec2types.BlockDeviceMapping{} opts := buildRegisterOptsFromExistingImage(&config, &image, blockDevices, rootDeviceName, config.AMIName) - expected := config.AMIVirtType + expected := string(config.AMIVirtType) if *opts.VirtualizationType != expected { t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, *opts.VirtualizationType) } @@ -121,13 +120,13 @@ func TestStepRegisterAmi_buildRegisterOptFromExistingImage(t *testing.T) { FromScratch: false, PackerConfig: common.PackerConfig{}, } - sourceImage := ec2.Image{ + sourceImage := ec2types.Image{ RootDeviceName: &rootDeviceName, - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ + BlockDeviceMappings: []ec2types.BlockDeviceMapping{ { DeviceName: &rootDeviceName, - Ebs: &ec2.EbsBlockDevice{ - VolumeSize: aws.Int64(10), + Ebs: &ec2types.EbsBlockDevice{ + VolumeSize: aws.Int32(10), }, }, // Throw in an ephemeral device, it seems like all devices in the return struct in a source AMI have @@ -135,8 +134,8 @@ func TestStepRegisterAmi_buildRegisterOptFromExistingImage(t *testing.T) { { DeviceName: aws.String("/dev/sdb"), VirtualName: aws.String("ephemeral0"), - Ebs: &ec2.EbsBlockDevice{ - VolumeSize: aws.Int64(0), + Ebs: &ec2types.EbsBlockDevice{ + VolumeSize: aws.Int32(0), }, }, }, @@ -179,13 +178,13 @@ func TestStepRegisterAmi_buildRegisterOptFromExistingImageWithBlockDeviceMapping } // Intentionally try to use a different root devicename - sourceImage := ec2.Image{ + sourceImage := ec2types.Image{ RootDeviceName: aws.String(oldRootDevice), - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ + BlockDeviceMappings: []ec2types.BlockDeviceMapping{ { DeviceName: aws.String(oldRootDevice), - Ebs: &ec2.EbsBlockDevice{ - VolumeSize: aws.Int64(10), + Ebs: &ec2types.EbsBlockDevice{ + VolumeSize: aws.Int32(10), }, }, // Throw in an ephemeral device, it seems like all devices in the return struct in a source AMI have @@ -193,8 +192,8 @@ func TestStepRegisterAmi_buildRegisterOptFromExistingImageWithBlockDeviceMapping { DeviceName: aws.String("/dev/sdb"), VirtualName: aws.String("ephemeral0"), - Ebs: &ec2.EbsBlockDevice{ - VolumeSize: aws.Int64(0), + Ebs: &ec2types.EbsBlockDevice{ + VolumeSize: aws.Int32(0), }, }, }, diff --git a/builder/chroot/step_snapshot.go b/builder/chroot/step_snapshot.go index 3bbd3abc..bfa099cf 100644 --- a/builder/chroot/step_snapshot.go +++ b/builder/chroot/step_snapshot.go @@ -8,8 +8,10 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -25,14 +27,15 @@ type StepSnapshot struct { } func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) + awscfg := state.Get("awsConfig").(*aws.Config) ui := state.Get("ui").(packersdk.Ui) volumeId := state.Get("volume_id").(string) ui.Say("Creating snapshot...") description := fmt.Sprintf("Packer: %s", time.Now().String()) - createSnapResp, err := ec2conn.CreateSnapshot(&ec2.CreateSnapshotInput{ + createSnapResp, err := ec2conn.CreateSnapshot(ctx, &ec2.CreateSnapshotInput{ VolumeId: &volumeId, Description: &description, }) @@ -59,7 +62,7 @@ func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multis state.Put("snapshot_id", s.snapshotId) snapshots := map[string][]string{ - *ec2conn.Config.Region: {s.snapshotId}, + awscfg.Region: {s.snapshotId}, } state.Put("snapshots", snapshots) @@ -71,14 +74,15 @@ func (s *StepSnapshot) Cleanup(state multistep.StateBag) { return } + ctx := state.Get("context").(context.Context) _, cancelled := state.GetOk(multistep.StateCancelled) _, halted := state.GetOk(multistep.StateHalted) if cancelled || halted { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Removing snapshot since we cancelled or halted...") - _, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{SnapshotId: &s.snapshotId}) + _, err := ec2conn.DeleteSnapshot(ctx, &ec2.DeleteSnapshotInput{SnapshotId: &s.snapshotId}) if err != nil { ui.Error(fmt.Sprintf("Error: %s", err)) } diff --git a/builder/common/access_config.go b/builder/common/access_config.go index fe44026c..8e474ba3 100644 --- a/builder/common/access_config.go +++ b/builder/common/access_config.go @@ -8,27 +8,17 @@ package common import ( "context" - "crypto/tls" "fmt" "log" - "net/http" "strings" "time" - awsv2 "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/aws" - awsCredentials "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" - awsbase "github.com/hashicorp/aws-sdk-go-base" - awsbase_v2 "github.com/hashicorp/aws-sdk-go-base/v2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + awsbase "github.com/hashicorp/aws-sdk-go-base/v2" basediag "github.com/hashicorp/aws-sdk-go-base/v2/diag" + "github.com/hashicorp/packer-plugin-amazon/common/clients" - cleanhttp "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" - pluginversion "github.com/hashicorp/packer-plugin-amazon/version" "github.com/hashicorp/packer-plugin-sdk/common" vaultapi "github.com/hashicorp/vault/api" ) @@ -163,8 +153,7 @@ type AccessConfig struct { // access key and secret key. If you're not sure what this is, then you // probably don't need it. This will also be read from the AWS_SESSION_TOKEN // environmental variable. - Token string `mapstructure:"token" required:"false"` - session *session.Session + Token string `mapstructure:"token" required:"false"` // Get credentials from HashiCorp Vault's aws secrets engine. You must // already have created a role to use. For more information about // generating credentials via the Vault engine, see the [Vault @@ -213,21 +202,21 @@ 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 + PollingConfig *AWSPollingConfig `mapstructure:"aws_polling" required:"false"` + awsConfig *aws.Config + getEC2Connection func() clients.Ec2Client // packerConfig is set by Prepare() containing information about Packer, // including the CorePackerVersionString packerConfig *common.PackerConfig } -func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*awsv2.Config, error) { +func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*aws.Config, error) { // Reload values into the config used by the Packer-Terraform shared SDK - assumeRoles := []awsbase_v2.AssumeRole{} + assumeRoles := []awsbase.AssumeRole{} if c.AssumeRole.AssumeRoleARN != "" { - awsbaseAssumeRole := awsbase_v2.AssumeRole{ + awsbaseAssumeRole := awsbase.AssumeRole{ RoleARN: c.AssumeRole.AssumeRoleARN, Duration: time.Duration(c.AssumeRole.AssumeRoleDurationSeconds) * time.Second, ExternalID: c.AssumeRole.AssumeRoleExternalID, @@ -240,7 +229,7 @@ func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*awsv2.Config, error) assumeRoles = append(assumeRoles, awsbaseAssumeRole) } - awsbaseConfig := awsbase_v2.Config{ + awsbaseConfig := awsbase.Config{ AccessKey: c.AccessKey, AssumeRole: assumeRoles, Insecure: c.InsecureSkipTLSVerify, @@ -252,7 +241,7 @@ func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*awsv2.Config, error) Token: c.Token, } - _, awsConfig, awsDiags := awsbase_v2.GetAwsConfig(ctx, &awsbaseConfig) + _, awsConfig, awsDiags := awsbase.GetAwsConfig(ctx, &awsbaseConfig) for _, d := range awsDiags { switch d.Severity() { @@ -268,110 +257,11 @@ func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*awsv2.Config, error) return &awsConfig, nil } -// Config returns a valid aws.Config object for access to AWS services, or -// an error if the authentication and region couldn't be resolved -func (c *AccessConfig) Session() (*session.Session, error) { - if c.session != nil { - return c.session, nil - } - - // Create new AWS config - config := aws.NewConfig().WithCredentialsChainVerboseErrors(true) - if c.MaxRetries > 0 { - config = config.WithMaxRetries(c.MaxRetries) - } - - // Set AWS config defaults. - if c.RawRegion != "" { - config = config.WithRegion(c.RawRegion) - } - - if c.CustomEndpointEc2 != "" { - config = config.WithEndpoint(c.CustomEndpointEc2) - } - - config = config.WithHTTPClient(cleanhttp.DefaultClient()) - transport := config.HTTPClient.Transport.(*http.Transport) - if c.InsecureSkipTLSVerify { - transport.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - transport.Proxy = http.ProxyFromEnvironment - - // Figure out which possible credential providers are valid; test that we - // can get credentials via the selected providers, and set the providers in - // the config. - creds, err := c.GetCredentials(config) - if err != nil { - return nil, err - } - config.WithCredentials(creds) - - // Create session options based on our AWS config - opts := session.Options{ - SharedConfigState: session.SharedConfigEnable, - Config: *config, - } - - if c.ProfileName != "" { - opts.Profile = c.ProfileName - } - - if c.MFACode != "" { - opts.AssumeRoleTokenProvider = func() (string, error) { - return c.MFACode, nil - } - } - - sess, err := session.NewSessionWithOptions(opts) - if err != nil { - return nil, err - } - log.Printf("Found region %s", *sess.Config.Region) - c.session = sess - - cp, err := c.session.Config.Credentials.Get() - - if awserrors.Matches(err, "NoCredentialProviders", "") { - return nil, c.NewNoValidCredentialSourcesError(err) - } - - if err != nil { - return nil, fmt.Errorf("Error loading credentials for AWS Provider: %s", err) - } - - log.Printf("[INFO] AWS Auth provider used: %q", cp.ProviderName) - - if c.DecodeAuthZMessages { - DecodeAuthZMessages(c.session) - } - - // Append additional User-Agent products to the AWS SDK Go client. - userAgentProducts := []*awsbase.UserAgentProduct{ - {Name: "APN", Version: "1.0"}, - {Name: "HashiCorp", Version: "1.0"}, - {Name: "packer-plugin-amazon", Version: pluginversion.Version, Extra: []string{"+https://www.packer.io/docs/builders/amazon"}}, - } - - if c.packerConfig != nil { - // In acceptance tests, this is nil when authenticating for cleaning up created resources. - userAgentProducts = append(userAgentProducts, &awsbase.UserAgentProduct{Name: "Packer", Version: c.packerConfig.PackerCoreVersion, Extra: []string{"+https://www.packer.io"}}) - } - - for i := len(userAgentProducts) - 1; i >= 0; i-- { - product := userAgentProducts[i] - c.session.Handlers.Build.PushFront(request.MakeAddToUserAgentHandler(product.Name, product.Version, product.Extra...)) - } - - return c.session, nil -} - func (c *AccessConfig) SessionRegion() string { - if c.session == nil { - panic("access config session should be set.") + if c.awsConfig == nil { + panic("access config should be set.") } - return aws.StringValue(c.session.Config.Region) + return c.awsConfig.Region } func (c *AccessConfig) IsGovCloud() bool { @@ -382,46 +272,6 @@ func (c *AccessConfig) IsChinaCloud() bool { return strings.HasPrefix(c.SessionRegion(), "cn-") } -// GetCredentials gets credentials from the environment, shared credentials, -// the session (which may include a credential process), or ECS/EC2 metadata -// endpoints. GetCredentials also validates the credentials and the ability to -// assume a role or will return an error if unsuccessful. -func (c *AccessConfig) GetCredentials(config *aws.Config) (*awsCredentials.Credentials, error) { - packerDebug := false - if c.packerConfig != nil && c.packerConfig.PackerDebug { - packerDebug = true - } - // Reload values into the config used by the Packer-Terraform shared SDK - awsbaseConfig := &awsbase.Config{ - AccessKey: c.AccessKey, - AssumeRoleARN: c.AssumeRole.AssumeRoleARN, - AssumeRoleDurationSeconds: c.AssumeRole.AssumeRoleDurationSeconds, - AssumeRoleExternalID: c.AssumeRole.AssumeRoleExternalID, - AssumeRolePolicy: c.AssumeRole.AssumeRolePolicy, - AssumeRolePolicyARNs: c.AssumeRole.AssumeRolePolicyARNs, - AssumeRoleSessionName: c.AssumeRole.AssumeRoleSessionName, - AssumeRoleTags: c.AssumeRole.AssumeRoleTags, - AssumeRoleTransitiveTagKeys: c.AssumeRole.AssumeRoleTransitiveTagKeys, - CredsFilename: c.CredsFilename, - DebugLogging: packerDebug, - // TODO: implement for Packer - // IamEndpoint: c.Endpoints["iam"], - Insecure: c.InsecureSkipTLSVerify, - MaxRetries: c.MaxRetries, - Profile: c.ProfileName, - Region: c.RawRegion, - SecretKey: c.SecretKey, - SkipCredsValidation: c.SkipCredsValidation, - SkipMetadataApiCheck: c.SkipMetadataApiCheck, - // TODO: implement for Packer - // SkipRequestingAccountId: c.SkipRequestingAccountId, - // StsEndpoint: c.Endpoints["sts"], - Token: c.Token, - } - - return awsbase.GetCredentials(awsbaseConfig) -} - func (c *AccessConfig) getCredsFromVault(cli *vaultapi.Client) (*vaultapi.Secret, error) { if len(c.VaultAWSEngine.RoleARN) > 0 { data := map[string]interface{}{ @@ -529,16 +379,20 @@ func (c *AccessConfig) NewNoValidCredentialSourcesError(err error) error { "Error: %w", err) } -func (c *AccessConfig) NewEC2Connection() (ec2iface.EC2API, error) { +func (c *AccessConfig) NewEC2Connection(ctx context.Context) (clients.Ec2Client, error) { if c.getEC2Connection != nil { return c.getEC2Connection(), nil } - sess, err := c.Session() + awscfg, err := c.GetAWSConfig(ctx) if err != nil { return nil, err } - ec2conn := ec2.New(sess) - + ec2conn := ec2.NewFromConfig(awscfg.Copy(), func(o *ec2.Options) { + o.Region = c.SessionRegion() + if c.CustomEndpointEc2 != "" { + o.BaseEndpoint = aws.String(c.CustomEndpointEc2) + } + }) return ec2conn, nil } diff --git a/builder/common/access_config_test.go b/builder/common/access_config_test.go index 8ac2af11..f3566a73 100644 --- a/builder/common/access_config_test.go +++ b/builder/common/access_config_test.go @@ -6,8 +6,6 @@ package common import ( "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/hashicorp/packer-plugin-sdk/common" ) @@ -15,19 +13,19 @@ func TestAccessConfigPrepare_Region(t *testing.T) { c := FakeAccessConfig() c.RawRegion = "us-east-12" - err := c.ValidateRegion(c.RawRegion) + err := c.ValidateRegion(t.Context(), c.RawRegion) if err == nil { t.Fatalf("should have region validation err: %s", c.RawRegion) } c.RawRegion = "us-east-1" - err = c.ValidateRegion(c.RawRegion) + err = c.ValidateRegion(t.Context(), c.RawRegion) if err != nil { t.Fatalf("shouldn't have region validation err: %s", c.RawRegion) } c.RawRegion = "custom" - err = c.ValidateRegion(c.RawRegion) + err = c.ValidateRegion(t.Context(), c.RawRegion) if err == nil { t.Fatalf("should have region validation err: %s", c.RawRegion) } @@ -36,10 +34,14 @@ func TestAccessConfigPrepare_Region(t *testing.T) { func TestAccessConfigPrepare_RegionRestricted(t *testing.T) { c := FakeAccessConfig() - // Create a Session with a custom region - c.session = session.Must(session.NewSession(&aws.Config{ - Region: aws.String("us-gov-west-1"), - })) + awscfg, err := c.GetAWSConfig(t.Context()) + if err != nil { + t.Fatalf("shouldn't have err: %s", err) + } + + // Create config with a custom region + *c.awsConfig = awscfg.Copy() + c.awsConfig.Region = "us-gov-west-1" packerConfig := &common.PackerConfig{ PackerCoreVersion: "0.0.0", @@ -56,10 +58,14 @@ func TestAccessConfigPrepare_RegionRestricted(t *testing.T) { func TestAccessConfigPrepare_UnknownPackerCoreVersion(t *testing.T) { c := FakeAccessConfig() - // Create a Session with a custom region - c.session = session.Must(session.NewSession(&aws.Config{ - Region: aws.String("us-east-1"), - })) + awscfg, err := c.GetAWSConfig(t.Context()) + if err != nil { + t.Fatalf("shouldn't have err: %s", err) + } + + // Create config with a custom region + *c.awsConfig = awscfg.Copy() + c.awsConfig.Region = "us-east-1" if err := c.Prepare(nil); err != nil { t.Fatalf("shouldn't have err: %s", err) diff --git a/builder/common/ami_config.go b/builder/common/ami_config.go index c90bc159..7e29baec 100644 --- a/builder/common/ami_config.go +++ b/builder/common/ami_config.go @@ -12,7 +12,7 @@ import ( "regexp" "time" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" ) @@ -77,7 +77,7 @@ type AMIConfig struct { // The type of virtualization for the AMI // you are building. This option is required to register HVM images. Can be // paravirtual (default) or hvm. - AMIVirtType string `mapstructure:"ami_virtualization_type" required:"false"` + AMIVirtType ec2types.VirtualizationType `mapstructure:"ami_virtualization_type" required:"false"` // A list of account IDs that have access to // launch the resulting AMI(s). By default no additional users other than the // user creating the AMI has permissions to launch it. @@ -213,7 +213,7 @@ type AMIConfig struct { // Valid options are unset (legacy) and `v2.0`. See the documentation on // [IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) // for more information. Defaults to legacy. - AMIIMDSSupport string `mapstructure:"imds_support" required:"false"` + AMIIMDSSupport ec2types.ImdsSupportValues `mapstructure:"imds_support" required:"false"` // The date and time to deprecate the AMI, in UTC, in the following format: YYYY-MM-DDTHH:MM:SSZ. // If you specify a value for seconds, Amazon EC2 rounds the seconds to the nearest minute. // You can’t specify a date in the past. The upper limit for DeprecateAt is 10 years from now. @@ -321,10 +321,10 @@ func (c *AMIConfig) Prepare(accessConfig *AccessConfig, ctx *interpolate.Context "filter to automatically clean your ami name.")) } - if c.AMIIMDSSupport != "" && c.AMIIMDSSupport != ec2.ImdsSupportValuesV20 { + if c.AMIIMDSSupport != "" && c.AMIIMDSSupport != ec2types.ImdsSupportValuesV20 { errs = append(errs, fmt.Errorf(`The only valid imds_support values are %q or the empty string`, - ec2.ImdsSupportValuesV20), + ec2types.ImdsSupportValuesV20), ) } diff --git a/builder/common/ami_config_test.go b/builder/common/ami_config_test.go index 3e70289d..78020718 100644 --- a/builder/common/ami_config_test.go +++ b/builder/common/ami_config_test.go @@ -4,11 +4,13 @@ package common import ( + "context" "reflect" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/template/config" ) @@ -37,9 +39,9 @@ func TestAMIConfigPrepare_name(t *testing.T) { } } -func (m *mockEC2Client) DescribeRegions(*ec2.DescribeRegionsInput) (*ec2.DescribeRegionsOutput, error) { +func (m *mockEC2Client) DescribeRegions(ctx context.Context, params *ec2.DescribeRegionsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeRegionsOutput, error) { return &ec2.DescribeRegionsOutput{ - Regions: []*ec2.Region{ + Regions: []ec2types.Region{ {RegionName: aws.String("us-east-1")}, {RegionName: aws.String("us-east-2")}, {RegionName: aws.String("us-west-1")}, @@ -59,7 +61,7 @@ func TestAMIConfigPrepare_regions(t *testing.T) { t.Fatalf("shouldn't have err: %#v", errs) } - c.AMIRegions, err = listEC2Regions(mockConn) + c.AMIRegions, err = listEC2Regions(t.Context(), mockConn) if err != nil { t.Fatalf("shouldn't have err: %s", err.Error()) } diff --git a/builder/common/ami_filter.go b/builder/common/ami_filter.go index 77e85bd1..a52db3a5 100644 --- a/builder/common/ami_filter.go +++ b/builder/common/ami_filter.go @@ -5,10 +5,13 @@ package common import ( + "context" "fmt" "log" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" ) type AmiFilterOptions struct { @@ -31,11 +34,11 @@ type AmiFilterOptions struct { IncludeDeprecated bool `mapstructure:"include_deprecated"` } -func (d *AmiFilterOptions) GetOwners() []*string { - res := make([]*string, 0, len(d.Owners)) +func (d *AmiFilterOptions) GetOwners() []string { + res := make([]string, 0, len(d.Owners)) for _, owner := range d.Owners { i := owner - res = append(res, &i) + res = append(res, i) } return res } @@ -48,7 +51,7 @@ func (d *AmiFilterOptions) NoOwner() bool { return len(d.Owners) == 0 } -func (d *AmiFilterOptions) GetFilteredImage(params *ec2.DescribeImagesInput, ec2conn *ec2.EC2) (*ec2.Image, error) { +func (d *AmiFilterOptions) GetFilteredImage(ctx context.Context, params *ec2.DescribeImagesInput, ec2conn clients.Ec2Client) (*ec2types.Image, error) { // We have filters to apply if len(d.Filters) > 0 { amiFilters, err := buildEc2Filters(d.Filters) @@ -65,10 +68,10 @@ func (d *AmiFilterOptions) GetFilteredImage(params *ec2.DescribeImagesInput, ec2 params.IncludeDeprecated = &d.IncludeDeprecated log.Printf("Using AMI Filters %v", params) - req, imageResp := ec2conn.DescribeImagesRequest(params) - req.RetryCount = 11 + imageResp, err := ec2conn.DescribeImages(ctx, params, func(o *ec2.Options) { + o.RetryMaxAttempts = 11 + }) - err := req.Send() if err != nil { err := fmt.Errorf("Error querying AMI: %s", err) return nil, err @@ -84,11 +87,11 @@ func (d *AmiFilterOptions) GetFilteredImage(params *ec2.DescribeImagesInput, ec2 return nil, err } - var image *ec2.Image + var image ec2types.Image if d.MostRecent { image = mostRecentAmi(imageResp.Images) } else { image = imageResp.Images[0] } - return image, nil + return &image, nil } diff --git a/builder/common/artifact.go b/builder/common/artifact.go index 6ef433cb..7a8b0cec 100644 --- a/builder/common/artifact.go +++ b/builder/common/artifact.go @@ -4,14 +4,14 @@ package common import ( + "context" "fmt" "log" "sort" "strings" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image" ) @@ -28,8 +28,8 @@ type Artifact struct { // to be shared with post-processors StateData map[string]interface{} - // EC2 connection for performing API stuff. - Session *session.Session + // AWS SDK v2 configuration + Config *aws.Config } func (a *Artifact) BuilderId() string { @@ -82,16 +82,17 @@ func (a *Artifact) State(name string) interface{} { func (a *Artifact) Destroy() error { errors := make([]error, 0) + ctx := context.TODO() for region, imageId := range a.Amis { log.Printf("Deregistering image ID (%s) from region (%s)", imageId, region) - regionConn := ec2.New(a.Session, &aws.Config{ - Region: aws.String(region), + regionConn := ec2.NewFromConfig(*a.Config, func(o *ec2.Options) { + o.Region = region }) // Get image metadata - imageResp, err := regionConn.DescribeImages(&ec2.DescribeImagesInput{ - ImageIds: []*string{&imageId}, + imageResp, err := regionConn.DescribeImages(ctx, &ec2.DescribeImagesInput{ + ImageIds: []string{imageId}, }) if err != nil { errors = append(errors, err) @@ -101,7 +102,7 @@ func (a *Artifact) Destroy() error { errors = append(errors, err) } - err = DestroyAMIs([]*string{&imageId}, regionConn) + err = DestroyAMIs(ctx, []string{imageId}, regionConn) if err != nil { errors = append(errors, err) } diff --git a/builder/common/block_device.go b/builder/common/block_device.go index be70a230..b70f8268 100644 --- a/builder/common/block_device.go +++ b/builder/common/block_device.go @@ -10,8 +10,8 @@ import ( "fmt" "strings" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" ) @@ -81,7 +81,7 @@ type BlockDevice struct { // See the documentation on // [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) // for more information - IOPS *int64 `mapstructure:"iops" required:"false"` + IOPS *int32 `mapstructure:"iops" required:"false"` // Suppresses the specified device included in the block device mapping of // the AMI. NoDevice bool `mapstructure:"no_device" required:"false"` @@ -91,7 +91,7 @@ type BlockDevice struct { // See the documentation on // [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) // for more information - Throughput *int64 `mapstructure:"throughput" required:"false"` + Throughput *int32 `mapstructure:"throughput" required:"false"` // The virtual device name. See the documentation on // [Block Device Mapping](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html) // for more information. @@ -104,10 +104,10 @@ type BlockDevice struct { // The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2 // for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, // sc1 for Cold HDD, and standard for Magnetic volumes. - VolumeType string `mapstructure:"volume_type" required:"false"` + VolumeType ec2types.VolumeType `mapstructure:"volume_type" required:"false"` // The size of the volume, in GiB. Required if not specifying a // snapshot_id. - VolumeSize int64 `mapstructure:"volume_size" required:"false"` + VolumeSize int32 `mapstructure:"volume_size" required:"false"` // ID, alias or ARN of the KMS key to use for boot volume encryption. // This option exists for launch_block_device_mappings but not // ami_block_device_mappings. The kms key id defined here only applies to @@ -122,8 +122,8 @@ type BlockDevice struct { type BlockDevices []BlockDevice -func (bds BlockDevices) BuildEC2BlockDeviceMappings() []*ec2.BlockDeviceMapping { - var blockDevices []*ec2.BlockDeviceMapping +func (bds BlockDevices) BuildEC2BlockDeviceMappings() []ec2types.BlockDeviceMapping { + var blockDevices []ec2types.BlockDeviceMapping for _, blockDevice := range bds { blockDevices = append(blockDevices, blockDevice.BuildEC2BlockDeviceMapping()) @@ -131,9 +131,9 @@ func (bds BlockDevices) BuildEC2BlockDeviceMappings() []*ec2.BlockDeviceMapping return blockDevices } -func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapping { +func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() ec2types.BlockDeviceMapping { - mapping := &ec2.BlockDeviceMapping{ + mapping := ec2types.BlockDeviceMapping{ DeviceName: aws.String(blockDevice.DeviceName), } @@ -147,25 +147,25 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapp return mapping } - ebsBlockDevice := &ec2.EbsBlockDevice{ + ebsBlockDevice := &ec2types.EbsBlockDevice{ DeleteOnTermination: aws.Bool(blockDevice.DeleteOnTermination), } if blockDevice.VolumeType != "" { - ebsBlockDevice.VolumeType = aws.String(blockDevice.VolumeType) + ebsBlockDevice.VolumeType = blockDevice.VolumeType } if blockDevice.VolumeSize > 0 { - ebsBlockDevice.VolumeSize = aws.Int64(blockDevice.VolumeSize) + ebsBlockDevice.VolumeSize = aws.Int32(blockDevice.VolumeSize) } switch blockDevice.VolumeType { - case "io1", "io2", "gp3": + case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2, ec2types.VolumeTypeGp3: ebsBlockDevice.Iops = blockDevice.IOPS } // Throughput is only valid for gp3 types - if blockDevice.VolumeType == "gp3" { + if blockDevice.VolumeType == ec2types.VolumeTypeGp3 { ebsBlockDevice.Throughput = blockDevice.Throughput } @@ -184,9 +184,9 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapp return mapping } -var iopsRatios = map[string]int64{ - "io1": 50, - "io2": 500, +var iopsRatios = map[ec2types.VolumeType]int32{ + ec2types.VolumeTypeIo1: 50, + ec2types.VolumeTypeIo2: 500, } func (b *BlockDevice) Prepare(ctx *interpolate.Context) error { diff --git a/builder/common/block_device_test.go b/builder/common/block_device_test.go index 713acac6..ac5969ae 100644 --- a/builder/common/block_device_test.go +++ b/builder/common/block_device_test.go @@ -6,8 +6,8 @@ package common import ( "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/google/go-cmp/cmp" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" @@ -16,7 +16,7 @@ import ( func TestBlockDevice(t *testing.T) { cases := []struct { Config *BlockDevice - Result *ec2.BlockDeviceMapping + Result *ec2types.BlockDeviceMapping }{ { Config: &BlockDevice{ @@ -27,12 +27,12 @@ func TestBlockDevice(t *testing.T) { DeleteOnTermination: true, }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ + Ebs: &ec2types.EbsBlockDevice{ SnapshotId: aws.String("snap-1234"), - VolumeType: aws.String("standard"), - VolumeSize: aws.Int64(8), + VolumeType: ec2types.VolumeTypeStandard, + VolumeSize: aws.Int32(8), DeleteOnTermination: aws.Bool(true), }, }, @@ -43,10 +43,10 @@ func TestBlockDevice(t *testing.T) { VolumeSize: 8, }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeSize: aws.Int64(8), + Ebs: &ec2types.EbsBlockDevice{ + VolumeSize: aws.Int32(8), DeleteOnTermination: aws.Bool(false), }, }, @@ -57,16 +57,16 @@ func TestBlockDevice(t *testing.T) { VolumeType: "io1", VolumeSize: 8, DeleteOnTermination: true, - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeType: aws.String("io1"), - VolumeSize: aws.Int64(8), + Ebs: &ec2types.EbsBlockDevice{ + VolumeType: ec2types.VolumeTypeIo1, + VolumeSize: aws.Int32(8), DeleteOnTermination: aws.Bool(true), - Iops: aws.Int64(1000), + Iops: aws.Int32(1000), }, }, }, @@ -76,16 +76,16 @@ func TestBlockDevice(t *testing.T) { VolumeType: "io2", VolumeSize: 8, DeleteOnTermination: true, - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeType: aws.String("io2"), - VolumeSize: aws.Int64(8), + Ebs: &ec2types.EbsBlockDevice{ + VolumeType: ec2types.VolumeTypeIo2, + VolumeSize: aws.Int32(8), DeleteOnTermination: aws.Bool(true), - Iops: aws.Int64(1000), + Iops: aws.Int32(1000), }, }, }, @@ -98,11 +98,11 @@ func TestBlockDevice(t *testing.T) { Encrypted: config.TriTrue, }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeType: aws.String("gp2"), - VolumeSize: aws.Int64(8), + Ebs: &ec2types.EbsBlockDevice{ + VolumeType: ec2types.VolumeTypeGp2, + VolumeSize: aws.Int32(8), DeleteOnTermination: aws.Bool(true), Encrypted: aws.Bool(true), }, @@ -118,11 +118,11 @@ func TestBlockDevice(t *testing.T) { KmsKeyId: "2Fa48a521f-3aff-4b34-a159-376ac5d37812", }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeType: aws.String("gp2"), - VolumeSize: aws.Int64(8), + Ebs: &ec2types.EbsBlockDevice{ + VolumeType: ec2types.VolumeTypeGp2, + VolumeSize: aws.Int32(8), DeleteOnTermination: aws.Bool(true), Encrypted: aws.Bool(true), KmsKeyId: aws.String("2Fa48a521f-3aff-4b34-a159-376ac5d37812"), @@ -136,10 +136,10 @@ func TestBlockDevice(t *testing.T) { DeleteOnTermination: true, }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeType: aws.String("standard"), + Ebs: &ec2types.EbsBlockDevice{ + VolumeType: ec2types.VolumeTypeStandard, DeleteOnTermination: aws.Bool(true), }, }, @@ -150,7 +150,7 @@ func TestBlockDevice(t *testing.T) { VirtualName: "ephemeral0", }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), VirtualName: aws.String("ephemeral0"), }, @@ -161,7 +161,7 @@ func TestBlockDevice(t *testing.T) { NoDevice: true, }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), NoDevice: aws.String(""), }, @@ -171,19 +171,19 @@ func TestBlockDevice(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "gp3", VolumeSize: 8, - Throughput: aws.Int64(125), - IOPS: aws.Int64(3000), + Throughput: aws.Int32(125), + IOPS: aws.Int32(3000), DeleteOnTermination: true, Encrypted: config.TriTrue, }, - Result: &ec2.BlockDeviceMapping{ + Result: &ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), - Ebs: &ec2.EbsBlockDevice{ - VolumeType: aws.String("gp3"), - VolumeSize: aws.Int64(8), - Throughput: aws.Int64(125), - Iops: aws.Int64(3000), + Ebs: &ec2types.EbsBlockDevice{ + VolumeType: ec2types.VolumeTypeGp3, + VolumeSize: aws.Int32(8), + Throughput: aws.Int32(125), + Iops: aws.Int32(3000), DeleteOnTermination: aws.Bool(true), Encrypted: aws.Bool(true), }, @@ -196,7 +196,7 @@ func TestBlockDevice(t *testing.T) { var launchBlockDevices BlockDevices = []BlockDevice{*tc.Config} - expected := []*ec2.BlockDeviceMapping{tc.Result} + expected := []*ec2types.BlockDeviceMapping{tc.Result} amiResults := amiBlockDevices.BuildEC2BlockDeviceMappings() if diff := cmp.Diff(expected, amiResults); diff != "" { @@ -222,7 +222,7 @@ func TestIOPSValidation(t *testing.T) { device: BlockDevice{ DeviceName: "/dev/sdb", VolumeType: "io1", - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, ok: true, }, @@ -230,7 +230,7 @@ func TestIOPSValidation(t *testing.T) { device: BlockDevice{ DeviceName: "/dev/sdb", VolumeType: "io2", - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, ok: true, }, @@ -240,7 +240,7 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "io1", VolumeSize: 50, - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, ok: true, }, @@ -249,7 +249,7 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "io2", VolumeSize: 100, - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, ok: true, }, @@ -259,7 +259,7 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "io1", VolumeSize: 10, - IOPS: aws.Int64(2000), + IOPS: aws.Int32(2000), }, ok: false, msg: "/dev/sdb: the maximum ratio of provisioned IOPS to requested volume size (in GiB) is 50:1 for io1 volumes", @@ -269,7 +269,7 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "io2", VolumeSize: 50, - IOPS: aws.Int64(30000), + IOPS: aws.Int32(30000), }, ok: false, msg: "/dev/sdb: the maximum ratio of provisioned IOPS to requested volume size (in GiB) is 500:1 for io2 volumes", @@ -280,7 +280,7 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "io2", VolumeSize: 500, - IOPS: aws.Int64(99999), + IOPS: aws.Int32(99999), }, ok: false, msg: "IOPS must be between 100 and 64000 for device /dev/sdb", @@ -291,7 +291,7 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "io2", VolumeSize: 50, - IOPS: aws.Int64(10), + IOPS: aws.Int32(10), }, ok: false, msg: "IOPS must be between 100 and 64000 for device /dev/sdb", @@ -302,8 +302,8 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "gp3", VolumeSize: 50, - Throughput: aws.Int64(125), - IOPS: aws.Int64(99999), + Throughput: aws.Int32(125), + IOPS: aws.Int32(99999), }, ok: false, msg: "IOPS must be between 3000 and 16000 for device /dev/sdb", @@ -314,8 +314,8 @@ func TestIOPSValidation(t *testing.T) { DeviceName: "/dev/sdb", VolumeType: "gp3", VolumeSize: 50, - Throughput: aws.Int64(125), - IOPS: aws.Int64(10), + Throughput: aws.Int32(125), + IOPS: aws.Int32(10), }, ok: false, msg: "IOPS must be between 3000 and 16000 for device /dev/sdb", @@ -348,18 +348,18 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(125), - IOPS: aws.Int64(3000), + VolumeType: ec2types.VolumeTypeGp3, + Throughput: aws.Int32(125), + IOPS: aws.Int32(3000), }, ok: true, }, { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(1000), - IOPS: aws.Int64(3000), + VolumeType: ec2types.VolumeTypeGp3, + Throughput: aws.Int32(1000), + IOPS: aws.Int32(3000), }, ok: true, }, @@ -367,9 +367,9 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(1001), - IOPS: aws.Int64(3000), + VolumeType: ec2types.VolumeTypeGp3, + Throughput: aws.Int32(1001), + IOPS: aws.Int32(3000), }, ok: false, msg: "Throughput must be between 125 and 1000 for device /dev/sdb", @@ -378,9 +378,9 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(124), - IOPS: aws.Int64(3000), + VolumeType: ec2types.VolumeTypeGp3, + Throughput: aws.Int32(124), + IOPS: aws.Int32(3000), }, ok: false, msg: "Throughput must be between 125 and 1000 for device /dev/sdb", diff --git a/builder/common/boot_mode_validation.go b/builder/common/boot_mode_validation.go index cbc028d5..80832a13 100644 --- a/builder/common/boot_mode_validation.go +++ b/builder/common/boot_mode_validation.go @@ -3,11 +3,15 @@ package common -import "fmt" +import ( + "fmt" + + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" +) // IsValidBootMode checks that the bootmode is a value supported by AWS -func IsValidBootMode(bootmode string) error { - validModes := []string{"legacy-bios", "uefi", "uefi-preferred"} +func IsValidBootMode(bootmode ec2types.BootModeValues) error { + validModes := []ec2types.BootModeValues{ec2types.BootModeValuesLegacyBios, ec2types.BootModeValuesUefi, ec2types.BootModeValuesUefiPreferred} for _, mode := range validModes { if bootmode == mode { diff --git a/builder/common/boot_mode_validation_test.go b/builder/common/boot_mode_validation_test.go index 0cc4184f..43bb0da2 100644 --- a/builder/common/boot_mode_validation_test.go +++ b/builder/common/boot_mode_validation_test.go @@ -3,7 +3,11 @@ package common -import "testing" +import ( + "testing" + + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" +) func TestIsValidBuildMode(t *testing.T) { tests := []struct { @@ -35,7 +39,7 @@ func TestIsValidBuildMode(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := IsValidBootMode(tt.value) + err := IsValidBootMode(ec2types.BootModeValues(tt.value)) if (err != nil) != tt.expectError { t.Errorf("error mismatch, expected %t, got %t", tt.expectError, err != nil) if err != nil { diff --git a/builder/common/build_filter.go b/builder/common/build_filter.go index 068693bb..2828b644 100644 --- a/builder/common/build_filter.go +++ b/builder/common/build_filter.go @@ -7,15 +7,15 @@ import ( "encoding/csv" "strings" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) // Build a slice of EC2 (AMI/Subnet/VPC) filter options from the filters provided. -func buildEc2Filters(input map[string]string) ([]*ec2.Filter, error) { - var filters []*ec2.Filter +func buildEc2Filters(input map[string]string) ([]ec2types.Filter, error) { + var filters []ec2types.Filter for k, v := range input { - var b []*string + var b []string a := k csvReader := csv.NewReader(strings.NewReader(v)) @@ -28,10 +28,10 @@ func buildEc2Filters(input map[string]string) ([]*ec2.Filter, error) { } for _, r := range values { var value = r - b = append(b, &value) + b = append(b, value) } - filters = append(filters, &ec2.Filter{ + filters = append(filters, ec2types.Filter{ Name: &a, Values: b, }) diff --git a/builder/common/build_filter_test.go b/builder/common/build_filter_test.go index 502d9fba..2903843e 100644 --- a/builder/common/build_filter_test.go +++ b/builder/common/build_filter_test.go @@ -37,7 +37,7 @@ func TestStepSourceAmiInfo_BuildFilter_SingleValue(t *testing.T) { foundMap := map[string]bool{filter_key: false, filter_key2: false} for _, filter := range outputFilter { for key, value := range testFilter { - if *filter.Name == key && *filter.Values[0] == value { + if *filter.Name == key && filter.Values[0] == value { foundMap[key] = true } } @@ -81,7 +81,7 @@ func TestStepSourceAmiInfo_BuildFilter_ListValue(t *testing.T) { for key, value := range testFilter { if *filter.Name == key { for idx, filter_value := range value { - if *filter.Values[idx] == filter_value { + if filter.Values[idx] == filter_value { foundMap[key] = true } else { foundMap[key] = false @@ -123,7 +123,7 @@ func TestStepSourceAmiInfo_BuildFilter_ValueWithQuote(t *testing.T) { foundMap := map[string]bool{filter_key: false, filter_key2: false} for _, filter := range outputFilter { for key, value := range testFilter { - if *filter.Name == key && *filter.Values[0] == value { + if *filter.Name == key && filter.Values[0] == value { foundMap[key] = true } } diff --git a/builder/common/helper_funcs.go b/builder/common/helper_funcs.go index ff3ea5d5..d29f41fd 100644 --- a/builder/common/helper_funcs.go +++ b/builder/common/helper_funcs.go @@ -9,15 +9,16 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/retry" ) // DestroyAMIs deregisters the AWS machine images in imageids from an active AWS account -func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { - resp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ +func DestroyAMIs(ctx context.Context, imageids []string, ec2conn clients.Ec2Client) error { + resp, err := ec2conn.DescribeImages(ctx, &ec2.DescribeImagesInput{ ImageIds: imageids, }) @@ -37,7 +38,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - _, err := ec2conn.DeregisterImage(&ec2.DeregisterImageInput{ + _, err := ec2conn.DeregisterImage(ctx, &ec2.DeregisterImageInput{ ImageId: i.ImageId, }) return err @@ -51,7 +52,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { // Delete snapshot(s) by image for _, b := range i.BlockDeviceMappings { - if b.Ebs != nil && aws.StringValue(b.Ebs.SnapshotId) != "" { + if b.Ebs != nil && aws.ToString(b.Ebs.SnapshotId) != "" { err = retry.Config{ Tries: 11, @@ -60,7 +61,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - _, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{ + _, err := ec2conn.DeleteSnapshot(ctx, &ec2.DeleteSnapshotInput{ SnapshotId: b.Ebs.SnapshotId, }) return err diff --git a/builder/common/interpolate_build_info.go b/builder/common/interpolate_build_info.go index a07bf602..9c6250dd 100644 --- a/builder/common/interpolate_build_info.go +++ b/builder/common/interpolate_build_info.go @@ -4,8 +4,8 @@ package common import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata" ) @@ -28,19 +28,19 @@ func extractBuildInfo(region string, state multistep.StateBag, generatedData *pa } } - sourceAMI := rawSourceAMI.(*ec2.Image) + sourceAMI := rawSourceAMI.(*ec2types.Image) sourceAMITags := make(map[string]string, len(sourceAMI.Tags)) for _, tag := range sourceAMI.Tags { - sourceAMITags[aws.StringValue(tag.Key)] = aws.StringValue(tag.Value) + sourceAMITags[aws.ToString(tag.Key)] = aws.ToString(tag.Value) } buildInfoTemplate := &BuildInfoTemplate{ BuildRegion: region, - SourceAMI: aws.StringValue(sourceAMI.ImageId), - SourceAMICreationDate: aws.StringValue(sourceAMI.CreationDate), - SourceAMIName: aws.StringValue(sourceAMI.Name), - SourceAMIOwner: aws.StringValue(sourceAMI.OwnerId), - SourceAMIOwnerName: aws.StringValue(sourceAMI.ImageOwnerAlias), + SourceAMI: aws.ToString(sourceAMI.ImageId), + SourceAMICreationDate: aws.ToString(sourceAMI.CreationDate), + SourceAMIName: aws.ToString(sourceAMI.Name), + SourceAMIOwner: aws.ToString(sourceAMI.OwnerId), + SourceAMIOwnerName: aws.ToString(sourceAMI.ImageOwnerAlias), SourceAMITags: sourceAMITags, } diff --git a/builder/common/regions.go b/builder/common/regions.go index f773420e..79115e7b 100644 --- a/builder/common/regions.go +++ b/builder/common/regions.go @@ -4,14 +4,15 @@ package common import ( + "context" "fmt" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/hashicorp/packer-plugin-amazon/common/clients" ) -func listEC2Regions(ec2conn ec2iface.EC2API) ([]string, error) { +func listEC2Regions(ctx context.Context, ec2conn clients.Ec2Client) ([]string, error) { var regions []string - resultRegions, err := ec2conn.DescribeRegions(nil) + resultRegions, err := ec2conn.DescribeRegions(ctx, nil) if err != nil { return []string{}, err } @@ -26,13 +27,13 @@ func listEC2Regions(ec2conn ec2iface.EC2API) ([]string, error) { // and exists; otherwise an error. // ValidateRegion calls ec2conn.DescribeRegions to get the list of // regions available to this account. -func (c *AccessConfig) ValidateRegion(regions ...string) error { - ec2conn, err := c.NewEC2Connection() +func (c *AccessConfig) ValidateRegion(ctx context.Context, regions ...string) error { + ec2conn, err := c.NewEC2Connection(ctx) if err != nil { return err } - validRegions, err := listEC2Regions(ec2conn) + validRegions, err := listEC2Regions(ctx, ec2conn) if err != nil { return err } diff --git a/builder/common/run_config.go b/builder/common/run_config.go index 16dc8cf8..e3bf0f48 100644 --- a/builder/common/run_config.go +++ b/builder/common/run_config.go @@ -15,7 +15,7 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" @@ -75,7 +75,7 @@ type Placement struct { // // The default is "default", meaning shared tenancy. Allowed values are "default", // "dedicated" and "host". - Tenancy string `mapstructure:"tenancy" required:"false"` + Tenancy ec2types.Tenancy `mapstructure:"tenancy" required:"false"` } func (p Placement) Prepare() []error { @@ -87,7 +87,7 @@ func (p Placement) Prepare() []error { if p.HostId != "" || p.HostResourceGroupArn != "" { switch p.Tenancy { - case "", "host": + case "", ec2types.TenancyHost: default: errs = append(errs, fmt.Errorf("The tenancy should be `host` if either the `host_id` or `host_resource_group_arn` attributes are specified.")) } @@ -146,10 +146,10 @@ type RunConfig struct { // duration. Note: This parameter is no longer available to new customers // from July 1, 2021. [See Amazon's //documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances). - BlockDurationMinutes int64 `mapstructure:"block_duration_minutes" required:"false"` + BlockDurationMinutes int32 `mapstructure:"block_duration_minutes" required:"false"` // Set the preference for using a capacity reservation if one exists. // Either will be `open` or `none`. Defaults to `none` - CapacityReservationPreference string `mapstructure:"capacity_reservation_preference" required:"false"` + CapacityReservationPreference ec2types.CapacityReservationPreference `mapstructure:"capacity_reservation_preference" required:"false"` // Provide the specific EC2 Capacity Reservation ID that will be used // by Packer. CapacityReservationId string `mapstructure:"capacity_reservation_id" required:"false"` @@ -284,7 +284,7 @@ type RunConfig struct { InstanceInitiatedShutdownBehavior string `mapstructure:"shutdown_behavior" required:"false"` // The EC2 instance type to use while building the // AMI, such as t2.small. - InstanceType string `mapstructure:"instance_type" required:"true"` + InstanceType ec2types.InstanceType `mapstructure:"instance_type" required:"true"` // Filters used to populate the `security_group_ids` field. // // HCL2 Example: @@ -408,7 +408,7 @@ type RunConfig struct { // across the Spot Instance pools specified by the EC2 Fleet launch configuration. // If this option is not set, Packer will use default option provided by the SDK (currently `lowest-price`). // For more information, see [Amazon EC2 User Guide] (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html) - SpotAllocationStrategy string `mapstructure:"spot_allocation_strategy" required:"false"` + SpotAllocationStrategy ec2types.SpotAllocationStrategy `mapstructure:"spot_allocation_strategy" required:"false"` // a list of acceptable instance // types to run your build on. We will request a spot instance using the max // price of spot_price and the allocation strategy of "lowest price". @@ -418,7 +418,7 @@ type RunConfig struct { // This feature exists to help prevent situations where a Packer build fails // because a particular availability zone does not have capacity for the // specific instance_type requested in instance_type. - SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false"` + SpotInstanceTypes []ec2types.InstanceType `mapstructure:"spot_instance_types" required:"false"` // With Spot Instances, you pay the Spot price that's in effect for the // time period your instances are running. Spot Instance prices are set by // Amazon EC2 and adjust gradually based on long-term trends in supply and @@ -568,7 +568,7 @@ type RunConfig struct { // Refer to the [Placement docs](#placement-configuration) for more information on the supported attributes for placement configuration. Placement Placement `mapstructure:"placement" required:"false"` // Deprecated: Use Placement Tenancy instead. - Tenancy string `mapstructure:"tenancy" required:"false"` + Tenancy ec2types.Tenancy `mapstructure:"tenancy" required:"false"` // A list of IPv4/IPv6 CIDR blocks to be authorized access to the instance, when // packer is creating a temporary security group. // @@ -848,7 +848,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { } } - if c.SpotAllocationStrategy != "" && !slices.Contains(ec2.SpotAllocationStrategy_Values(), + if c.SpotAllocationStrategy != "" && !slices.Contains(c.SpotAllocationStrategy.Values(), c.SpotAllocationStrategy) { errs = append(errs, fmt.Errorf( "Unknown spot_allocation_strategy: %s", c.SpotAllocationStrategy)) @@ -896,7 +896,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf("Error: Instance Type: %s is not within the supported types for Unlimited credits. Supported instance types are T2, T3, and T4g", c.InstanceType)) } - if c.SpotPrice != "" && regexp.MustCompile(`^t2\.`).MatchString(c.InstanceType) { + if c.SpotPrice != "" && regexp.MustCompile(`^t2\.`).MatchString(string(c.InstanceType)) { errs = append(errs, fmt.Errorf("Error: Unlimited credits cannot be used in conjunction with Spot Instances")) } @@ -924,8 +924,8 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf(`capacity_reservation_preference only accepts 'none' or 'open' values`)) } - var tenancy string - tenancies := []string{c.Placement.Tenancy, c.Tenancy} + var tenancy ec2types.Tenancy + tenancies := []ec2types.Tenancy{c.Placement.Tenancy, c.Tenancy} for i := range tenancies { if tenancies[i] != "" { @@ -950,7 +950,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf("Error: Nitro Enclave cannot be used in conjunction with Spot Instances")) } // check if we have an instance in the t-line (burstable instances) - if strings.HasPrefix(c.InstanceType, "t") { + if strings.HasPrefix(string(c.InstanceType), "t") { errs = append(errs, fmt.Errorf("Error: Nitro Enclaves cannot be used in conjunction with burstable instance types: %s", c.InstanceType)) } } @@ -971,5 +971,5 @@ func (c *RunConfig) SSMAgentEnabled() bool { // of the following types T2, T3a, T3, T4g func (c *RunConfig) IsBurstableInstanceType() bool { r := `^t(:?2|3a?|4g)\.` - return regexp.MustCompile(r).MatchString(c.InstanceType) + return regexp.MustCompile(r).MatchString(string(c.InstanceType)) } diff --git a/builder/common/run_config_test.go b/builder/common/run_config_test.go index d6bf938c..bf68ccbf 100644 --- a/builder/common/run_config_test.go +++ b/builder/common/run_config_test.go @@ -9,6 +9,7 @@ import ( "regexp" "testing" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/communicator" ) @@ -151,7 +152,7 @@ func TestRunConfigPrepare_EnableUnlimitedCredits(t *testing.T) { tc := []struct { name string - instanceType string + instanceType ec2types.InstanceType enableCredits bool errorCount int }{ @@ -349,7 +350,7 @@ func TestRunConfigPrepare_TenancyBad(t *testing.T) { } func TestRunConfigPrepare_TenancyGood(t *testing.T) { - validTenancy := []string{"", "default", "dedicated", "host"} + validTenancy := []ec2types.Tenancy{"", "default", "dedicated", "host"} for _, vt := range validTenancy { c := testConfig() c.Tenancy = vt @@ -453,7 +454,7 @@ func TestRunConfigPrepare_InvalidTenantForHost(t *testing.T) { c := testConfig() c.Placement.HostId = tt.setHost c.Placement.HostResourceGroupArn = tt.setGroup - c.Placement.Tenancy = tt.setTenant + c.Placement.Tenancy = ec2types.Tenancy(tt.setTenant) errs := c.Prepare(nil) if len(errs) != tt.expectErrors { t.Errorf("expected %d errors, got %d", tt.expectErrors, len(errs)) @@ -466,10 +467,10 @@ func TestRunConfigPrepare_WithCapacityReservations(t *testing.T) { tests := []struct { name string reservationID string - reservationPreference string + reservationPreference ec2types.CapacityReservationPreference reservationARN string expectedReservationID string - expectedReservationPreference string + expectedReservationPreference ec2types.CapacityReservationPreference expectedReservationARN string expectError bool }{ diff --git a/builder/common/ssh.go b/builder/common/ssh.go index 3aa3789e..ea2d9f9a 100644 --- a/builder/common/ssh.go +++ b/builder/common/ssh.go @@ -4,19 +4,25 @@ package common import ( + "context" "errors" "fmt" "log" "time" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" ) type ec2Describer interface { - DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) + DescribeInstances(ctx context.Context, input *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) } +var _ ec2Describer = (clients.Ec2Client)(nil) + var ( // modified in tests sshHostSleepDuration = time.Second @@ -24,7 +30,7 @@ var ( // SSHHost returns a function that can be given to the SSH communicator // for determining the SSH address based on the instance DNS name. -func SSHHost(e ec2Describer, sshInterface string, host string) func(multistep.StateBag) (string, error) { +func SSHHost(ctx context.Context, e ec2Describer, sshInterface string, host string) func(multistep.StateBag) (string, error) { return func(state multistep.StateBag) (string, error) { if host != "" { log.Printf("Using host value: %s", host) @@ -38,7 +44,7 @@ func SSHHost(e ec2Describer, sshInterface string, host string) func(multistep.St const tries = 2 // <= with current structure to check result of describing `tries` times for j := 0; j <= tries; j++ { - i := state.Get("instance").(*ec2.Instance) + i := state.Get("instance").(*ec2types.Instance) if sshInterface != "" { switch sshInterface { case "public_ip": @@ -80,8 +86,8 @@ func SSHHost(e ec2Describer, sshInterface string, host string) func(multistep.St return host, nil } - r, err := e.DescribeInstances(&ec2.DescribeInstancesInput{ - InstanceIds: []*string{i.InstanceId}, + r, err := e.DescribeInstances(ctx, &ec2.DescribeInstancesInput{ + InstanceIds: []string{aws.ToString(i.InstanceId)}, }) if err != nil { return "", err diff --git a/builder/common/ssh_test.go b/builder/common/ssh_test.go index 85c2d6e0..7f243035 100644 --- a/builder/common/ssh_test.go +++ b/builder/common/ssh_test.go @@ -4,10 +4,12 @@ package common import ( + "context" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/multistep" ) @@ -85,9 +87,9 @@ func testSSHHost(t *testing.T, allowTries int, vpcId string, sshInterface string ipv6: ipv6, } - f := SSHHost(e, sshInterface, sshHostOverride) + f := SSHHost(t.Context(), e, sshInterface, sshHostOverride) st := &multistep.BasicStateBag{} - st.Put("instance", &ec2.Instance{ + st.Put("instance", &ec2types.Instance{ InstanceId: aws.String("instance-id"), }) @@ -118,10 +120,10 @@ type fakeEC2Describer struct { ipv6 string } -func (d *fakeEC2Describer) DescribeInstances(in *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { +func (d *fakeEC2Describer) DescribeInstances(ctx context.Context, in *ec2.DescribeInstancesInput, opts ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) { d.tries++ - instance := &ec2.Instance{ + instance := ec2types.Instance{ InstanceId: aws.String("instance-id"), } @@ -138,9 +140,9 @@ func (d *fakeEC2Describer) DescribeInstances(in *ec2.DescribeInstancesInput) (*e } out := &ec2.DescribeInstancesOutput{ - Reservations: []*ec2.Reservation{ + Reservations: []ec2types.Reservation{ { - Instances: []*ec2.Instance{instance}, + Instances: []ec2types.Instance{instance}, }, }, } diff --git a/builder/common/ssm/session.go b/builder/common/ssm/session.go index 0411d4cb..21852c84 100644 --- a/builder/common/ssm/session.go +++ b/builder/common/ssm/session.go @@ -12,29 +12,29 @@ import ( "strconv" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ssm" - "github.com/aws/aws-sdk-go/service/ssm/ssmiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ssm" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" + "github.com/hashicorp/packer-plugin-amazon/common/clients" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/retry" "github.com/hashicorp/packer-plugin-sdk/shell-local/localexec" ) type Session struct { - SvcClient ssmiface.SSMAPI + SvcClient *ssm.Client Region string InstanceID string LocalPort, RemotePort int - Ec2Conn *ec2.EC2 + Ec2Conn clients.Ec2Client } func (s Session) buildTunnelInput() *ssm.StartSessionInput { portNumber, localPortNumber := strconv.Itoa(s.RemotePort), strconv.Itoa(s.LocalPort) - params := map[string][]*string{ - "portNumber": []*string{aws.String(portNumber)}, - "localPortNumber": []*string{aws.String(localPortNumber)}, + params := map[string][]string{ + "portNumber": []string{portNumber}, + "localPortNumber": []string{localPortNumber}, } return &ssm.StartSessionInput{ @@ -53,7 +53,7 @@ func (s Session) getCommand(ctx context.Context) ([]string, string, error) { ShouldRetry: func(err error) bool { return awserrors.Matches(err, "TargetNotConnected", "") }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) (err error) { - session, err = s.SvcClient.StartSessionWithContext(ctx, input) + session, err = s.SvcClient.StartSession(ctx, input) return err }) @@ -91,9 +91,9 @@ func (s Session) getCommand(ctx context.Context) ([]string, string, error) { // terminate an interactive Systems Manager session with a remote instance via the // AWS session-manager-plugin. Session cannot be resumed after termination. -func (s Session) terminateSession(sessionID string, ui packersdk.Ui) { +func (s Session) terminateSession(ctx context.Context, sessionID string, ui packersdk.Ui) { log.Printf("ssm: Terminating PortForwarding session %q", sessionID) - _, err := s.SvcClient.TerminateSession(&ssm.TerminateSessionInput{SessionId: aws.String(sessionID)}) + _, err := s.SvcClient.TerminateSession(ctx, &ssm.TerminateSessionInput{SessionId: aws.String(sessionID)}) if err != nil { ui.Error(fmt.Sprintf("Error terminating SSM Session %q, this does not affect the built AMI. Please terminate the session manually: %s", sessionID, err)) } @@ -125,22 +125,22 @@ func (s Session) Start(ctx context.Context, ui packersdk.Ui, sessionChan chan st // session will be terminated but exitSession is not set to true // because the instance is still running and we might want to do a reconnect case <-sessionFinished: - s.terminateSession(sessionID, ui) + s.terminateSession(ctx, sessionID, ui) return case <-timer.C: // wait for the session to be created - instanceState, err := s.Ec2Conn.DescribeInstanceStatus(&ec2.DescribeInstanceStatusInput{ - InstanceIds: []*string{aws.String(s.InstanceID)}, + instanceState, err := s.Ec2Conn.DescribeInstanceStatus(ctx, &ec2.DescribeInstanceStatusInput{ + InstanceIds: []string{s.InstanceID}, }) if err != nil { log.Printf("ssm: Error describing instance status: %s", err) } else if instanceState != nil && len(instanceState.InstanceStatuses) == 0 { // if no instance status is returned, the instance is terminated exitSession = true - s.terminateSession(sessionID, ui) + s.terminateSession(ctx, sessionID, ui) return } case <-ctx.Done(): - s.terminateSession(sessionID, ui) + s.terminateSession(ctx, sessionID, ui) return } } @@ -153,7 +153,7 @@ func (s Session) Start(ctx context.Context, ui packersdk.Ui, sessionChan chan st sessionChan <- struct{}{} cmd := exec.CommandContext(ctx, "session-manager-plugin", args...) - ui.Message(fmt.Sprintf("Starting portForwarding session %q.", sessionID)) + ui.Sayf("Starting portForwarding session %q.", sessionID) err = localexec.RunAndStream(cmd, ui, nil) sessionFinished <- struct{}{} if err != nil { diff --git a/builder/common/state.go b/builder/common/state.go index c95526d5..2e021749 100644 --- a/builder/common/state.go +++ b/builder/common/state.go @@ -6,6 +6,7 @@ package common import ( + "context" "fmt" "log" "os" @@ -13,10 +14,15 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/aws" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/smithy-go/middleware" + smithytime "github.com/aws/smithy-go/time" + smithywaiter "github.com/aws/smithy-go/waiter" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" ) @@ -76,11 +82,16 @@ type AWSPollingConfig struct { // 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"` + // Specifies the maximum timeout in seconds for the waiter. + // This value can also be set via the AWS_MAX_TIMEOUT. + // If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + // If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + MaxTimeout int `mapstructure:"max_timeout" required:"false"` } -func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.EC2API, imageId string) error { +func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx context.Context, conn clients.Ec2Client, imageId string) error { imageInput := ec2.DescribeImagesInput{ - ImageIds: []*string{&imageId}, + ImageIds: []string{imageId}, } log.Printf("Waiting for AMI (%s) to be available...", imageId) waitOpts := w.getWaiterOptions() @@ -89,10 +100,8 @@ func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface. // of ten minutes doesn't work for some of our long-running copies. waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(120)) } - err := conn.WaitUntilImageAvailableWithContext( - ctx, - &imageInput, - waitOpts...) + waiter := ec2.NewImageAvailableWaiter(conn) + err := waiter.Wait(ctx, &imageInput, time.Duration(w.MaxTimeout)*time.Second) if err != nil { if strings.Contains(err.Error(), request.WaiterResourceNotReadyErrorCode) { err = fmt.Errorf("Failed with ResourceNotReady error, which can "+ @@ -106,59 +115,51 @@ func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface. return err } -func (w *AWSPollingConfig) WaitUntilInstanceRunning(ctx aws.Context, conn ec2iface.EC2API, instanceId string) error { +func (w *AWSPollingConfig) WaitUntilInstanceRunning(ctx context.Context, conn clients.Ec2Client, instanceId string) error { instanceInput := ec2.DescribeInstancesInput{ - InstanceIds: []*string{&instanceId}, + InstanceIds: []string{instanceId}, } - err := conn.WaitUntilInstanceRunningWithContext( - ctx, - &instanceInput, - w.getWaiterOptions()...) + waiter := ec2.NewInstanceRunningWaiter(conn) + err := waiter.Wait(ctx, &instanceInput, time.Duration(w.MaxTimeout)*time.Second) return err } -func (w *AWSPollingConfig) WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId string) error { +func (w *AWSPollingConfig) WaitUntilInstanceTerminated(ctx context.Context, conn clients.Ec2Client, instanceId string) error { instanceInput := ec2.DescribeInstancesInput{ - InstanceIds: []*string{&instanceId}, + InstanceIds: []string{instanceId}, } - err := conn.WaitUntilInstanceTerminatedWithContext( - ctx, - &instanceInput, - w.getWaiterOptions()...) + waiter := ec2.NewInstanceTerminatedWaiter(conn) + err := waiter.Wait(ctx, &instanceInput, time.Duration(w.MaxTimeout)*time.Second) return err } // This function works for both requesting and cancelling spot instances. -func (w *AWSPollingConfig) WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId string) error { +func (w *AWSPollingConfig) WaitUntilSpotRequestFulfilled(ctx context.Context, conn clients.Ec2Client, spotRequestId string) error { spotRequestInput := ec2.DescribeSpotInstanceRequestsInput{ - SpotInstanceRequestIds: []*string{&spotRequestId}, + SpotInstanceRequestIds: []string{spotRequestId}, } - err := conn.WaitUntilSpotInstanceRequestFulfilledWithContext( - ctx, - &spotRequestInput, - w.getWaiterOptions()...) + waiter := ec2.NewSpotInstanceRequestFulfilledWaiter(conn) + err := waiter.Wait(ctx, &spotRequestInput, time.Duration(w.MaxTimeout)*time.Second) return err } -func (w *AWSPollingConfig) WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) error { +func (w *AWSPollingConfig) WaitUntilVolumeAvailable(ctx context.Context, conn clients.Ec2Client, volumeId string) error { volumeInput := ec2.DescribeVolumesInput{ - VolumeIds: []*string{&volumeId}, + VolumeIds: []string{volumeId}, } - err := conn.WaitUntilVolumeAvailableWithContext( - ctx, - &volumeInput, - w.getWaiterOptions()...) + waiter := ec2.NewVolumeAvailableWaiter(conn) + err := waiter.Wait(ctx, &volumeInput, time.Duration(w.MaxTimeout)*time.Second) return err } -func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx aws.Context, conn ec2iface.EC2API, snapshotID string) error { +func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx context.Context, conn clients.Ec2Client, snapshotID string) error { snapInput := ec2.DescribeSnapshotsInput{ - SnapshotIds: []*string{&snapshotID}, + SnapshotIds: []string{snapshotID}, } waitOpts := w.getWaiterOptions() @@ -168,207 +169,615 @@ func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx aws.Context, conn ec2iface. waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(120)) } - err := conn.WaitUntilSnapshotCompletedWithContext( - ctx, - &snapInput, - waitOpts...) + waiter := ec2.NewSnapshotCompletedWaiter(conn) + err := waiter.Wait(ctx, &snapInput, time.Duration(w.MaxTimeout)*time.Second) return err } // Wrappers for our custom AWS waiters -func (w *AWSPollingConfig) WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) error { +func (w *AWSPollingConfig) WaitUntilVolumeAttached(ctx context.Context, conn clients.Ec2Client, volumeId string) error { volumeInput := ec2.DescribeVolumesInput{ - VolumeIds: []*string{&volumeId}, + VolumeIds: []string{volumeId}, } - err := WaitForVolumeToBeAttached(conn, - ctx, - &volumeInput, - w.getWaiterOptions()...) + waiter := newVolumeAttachedWaiter(conn) + err := waiter.Wait(ctx, &volumeInput, time.Duration(w.MaxTimeout)*time.Second) return err } -func (w *AWSPollingConfig) WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) error { +func (w *AWSPollingConfig) WaitUntilVolumeDetached(ctx context.Context, conn clients.Ec2Client, volumeId string) error { volumeInput := ec2.DescribeVolumesInput{ - VolumeIds: []*string{&volumeId}, + VolumeIds: []string{volumeId}, } - err := WaitForVolumeToBeDetached(conn, - ctx, - &volumeInput, - w.getWaiterOptions()...) + waiter := newVolumeDetachedWaiter(conn) + err := waiter.Wait(ctx, &volumeInput, time.Duration(w.MaxTimeout)*time.Second) return err } -func (w *AWSPollingConfig) WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error { +func (w *AWSPollingConfig) WaitUntilImageImported(ctx context.Context, conn clients.Ec2Client, taskID string) error { importInput := ec2.DescribeImportImageTasksInput{ - ImportTaskIds: []*string{&taskID}, + ImportTaskIds: []string{taskID}, } - err := WaitForImageToBeImported(conn, - ctx, - &importInput, - w.getWaiterOptions()...) + waiter := newImportImageTaskWaiter(conn) + err := waiter.Wait(ctx, &importInput, time.Duration(w.MaxTimeout)*time.Second) return err } -func (w *AWSPollingConfig) WaitUntilFastLaunchEnabled(ctx aws.Context, conn *ec2.EC2, imageID string) error { +func (w *AWSPollingConfig) WaitUntilFastLaunchEnabled(ctx context.Context, conn clients.Ec2Client, imageID string) error { fastLaunchDescribeInput := &ec2.DescribeFastLaunchImagesInput{ - ImageIds: []*string{ - &imageID, - }, + ImageIds: []string{imageID}, } - err := WaitUntilFastLaunchEnabled(conn, - ctx, - fastLaunchDescribeInput, - w.getWaiterOptions()...) + waiter := newFastLaunchImageWaiter(conn) + err := waiter.Wait(ctx, fastLaunchDescribeInput, time.Duration(w.MaxTimeout)*time.Second) return err } -// Custom waiters using AWS's request.Waiter - -func WaitForVolumeToBeAttached(c *ec2.EC2, ctx aws.Context, input *ec2.DescribeVolumesInput, opts ...request.WaiterOption) error { - w := request.Waiter{ - Name: "DescribeVolumes", - MaxAttempts: 40, - Delay: request.ConstantWaiterDelay(5 * time.Second), - Acceptors: []request.WaiterAcceptor{ - { - State: request.SuccessWaiterState, - Matcher: request.PathAllWaiterMatch, - Argument: "Volumes[].Attachments[].State", - Expected: "attached", - }, - }, - Logger: c.Config.Logger, - NewRequest: func(opts []request.Option) (*request.Request, error) { - var inCpy *ec2.DescribeVolumesInput - if input != nil { - tmp := *input - inCpy = &tmp +// Custom SDK v2 waiters that we have to implement ourselves because the AWS SDK doesn't have built-in waiters for these actions. +type volumeAttachedDetachedWaiterOptions struct { + // Set of options to modify how an operation is invoked. These apply to all + // operations invoked for this client. Use functional options on operation call to + // modify this list for per operation behavior. + // + // Passing options here is functionally equivalent to passing values to this + // config's ClientOptions field that extend the inner client's APIOptions directly. + APIOptions []func(*middleware.Stack) error + + // Functional options to be passed to all operations invoked by this client. + // + // Function values that modify the inner APIOptions are applied after the waiter + // config's own APIOptions modifiers. + ClientOptions []func(*ec2.Options) + + // MinDelay is the minimum amount of time to delay between retries. If unset, + // VolumeInUseWaiter will use default minimum delay of 15 seconds. Note that + // MinDelay must resolve to a value lesser than or equal to the MaxDelay. + MinDelay time.Duration + + // MaxDelay is the maximum amount of time to delay between retries. If unset or + // set to zero, VolumeInUseWaiter will use default max delay of 120 seconds. Note + // that MaxDelay must resolve to value greater than or equal to the MinDelay. + MaxDelay time.Duration + + // LogWaitAttempts is used to enable logging for waiter retry attempts + LogWaitAttempts bool + + // Retryable is function that can be used to override the service defined + // waiter-behavior based on operation output, or returned error. This function is + // used by the waiter to decide if a state is retryable or a terminal state. + // + // By default service-modeled logic will populate this option. This option can + // thus be used to define a custom waiter state with fall-back to service-modeled + // waiter state mutators.The function returns an error in case of a failure state. + // In case of retry state, this function returns a bool value of true and nil + // error, while in case of success it returns a bool value of false and nil error. + Retryable func(context.Context, *ec2.DescribeVolumesInput, *ec2.DescribeVolumesOutput, error) (bool, error) +} + +type volumeAttachedDetachedWaiter struct { + client ec2.DescribeVolumesAPIClient + + options volumeAttachedDetachedWaiterOptions +} + +func (w *volumeAttachedDetachedWaiter) Wait(ctx context.Context, params *ec2.DescribeVolumesInput, maxWaitDur time.Duration, optFns ...func(*volumeAttachedDetachedWaiterOptions)) error { + if maxWaitDur <= 0 { + fmt.Errorf("maximum wait time for waiter must be greater than zero") + } + + options := w.options + for _, fn := range optFns { + fn(&options) + } + + if options.MaxDelay <= 0 { + options.MaxDelay = 120 * time.Second + } + + if options.MinDelay > options.MaxDelay { + return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) + } + + ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) + defer cancelFn() + + logger := smithywaiter.Logger{} + remainingTime := maxWaitDur + + var attempt int64 + for { + + attempt++ + apiOptions := options.APIOptions + start := time.Now() + + if options.LogWaitAttempts { + logger.Attempt = attempt + apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) + apiOptions = append(apiOptions, logger.AddLogger) + } + + out, err := w.client.DescribeVolumes(ctx, params, func(o *ec2.Options) { + baseOpts := []func(*ec2.Options){ + addIsWaiterUserAgent, } - req, _ := c.DescribeVolumesRequest(inCpy) - req.SetContext(ctx) - req.ApplyOptions(opts...) - return req, nil - }, - } - w.ApplyOptions(opts...) - - return w.WaitWithContext(ctx) -} - -func WaitForVolumeToBeDetached(c *ec2.EC2, ctx aws.Context, input *ec2.DescribeVolumesInput, opts ...request.WaiterOption) error { - w := request.Waiter{ - Name: "DescribeVolumes", - MaxAttempts: 40, - Delay: request.ConstantWaiterDelay(5 * time.Second), - Acceptors: []request.WaiterAcceptor{ - { - State: request.SuccessWaiterState, - Matcher: request.PathAllWaiterMatch, - Argument: "length(Volumes[].Attachments[]) == `0`", - Expected: true, - }, - }, - Logger: c.Config.Logger, - NewRequest: func(opts []request.Option) (*request.Request, error) { - var inCpy *ec2.DescribeVolumesInput - if input != nil { - tmp := *input - inCpy = &tmp + o.APIOptions = append(o.APIOptions, apiOptions...) + for _, opt := range baseOpts { + opt(o) } - req, _ := c.DescribeVolumesRequest(inCpy) - req.SetContext(ctx) - req.ApplyOptions(opts...) - return req, nil - }, - } - w.ApplyOptions(opts...) - - return w.WaitWithContext(ctx) -} - -func WaitForImageToBeImported(c *ec2.EC2, ctx aws.Context, input *ec2.DescribeImportImageTasksInput, opts ...request.WaiterOption) error { - w := request.Waiter{ - Name: "DescribeImages", - MaxAttempts: 720, - Delay: request.ConstantWaiterDelay(5 * time.Second), - Acceptors: []request.WaiterAcceptor{ - { - State: request.SuccessWaiterState, - Matcher: request.PathAllWaiterMatch, - Argument: "ImportImageTasks[].Status", - Expected: "completed", - }, - { - State: request.FailureWaiterState, - Matcher: request.PathAnyWaiterMatch, - Argument: "ImportImageTasks[].Status", - Expected: "deleted", - }, - }, - Logger: c.Config.Logger, - NewRequest: func(opts []request.Option) (*request.Request, error) { - var inCpy *ec2.DescribeImportImageTasksInput - if input != nil { - tmp := *input - inCpy = &tmp + for _, opt := range options.ClientOptions { + opt(o) } - req, _ := c.DescribeImportImageTasksRequest(inCpy) - req.SetContext(ctx) - req.ApplyOptions(opts...) - return req, nil - }, - } - w.ApplyOptions(opts...) - - return w.WaitWithContext(ctx) -} - -func WaitUntilFastLaunchEnabled(c *ec2.EC2, ctx aws.Context, input *ec2.DescribeFastLaunchImagesInput, opts ...request.WaiterOption) error { - w := request.Waiter{ - Name: "DescribeFastLaunchImages", - MaxAttempts: 500, - Delay: request.ConstantWaiterDelay(15 * time.Second), - Acceptors: []request.WaiterAcceptor{ - { - State: request.SuccessWaiterState, - Matcher: request.PathAllWaiterMatch, - Argument: "FastLaunchImages[].State", - Expected: "enabled", - }, - { - State: request.FailureWaiterState, - Matcher: request.PathAllWaiterMatch, - Argument: "FastLaunchImages[].State", - Expected: "enabling-failed", - }, - { - State: request.FailureWaiterState, - Matcher: request.PathAllWaiterMatch, - Argument: "FastLaunchImages[].State", - Expected: "enabled-failed", - }, - }, - Logger: c.Config.Logger, - NewRequest: func(opts []request.Option) (*request.Request, error) { - var inCpy *ec2.DescribeFastLaunchImagesInput - if input != nil { - tmp := *input - inCpy = &tmp + }) + + retryable, err := options.Retryable(ctx, params, out, err) + if err != nil { + return err + } + if !retryable { + return nil + } + + remainingTime -= time.Since(start) + if remainingTime < options.MinDelay || remainingTime <= 0 { + break + } + + // compute exponential backoff between waiter retries + delay, err := smithywaiter.ComputeDelay( + attempt, options.MinDelay, options.MaxDelay, remainingTime, + ) + if err != nil { + return fmt.Errorf("error computing waiter delay, %w", err) + } + + remainingTime -= delay + // sleep for the delay amount before invoking a request + if err := smithytime.SleepWithContext(ctx, delay); err != nil { + return fmt.Errorf("request cancelled while waiting, %w", err) + } + } + return fmt.Errorf("exceeded max wait time for VolumeAttached waiter") +} + +func newVolumeAttachedWaiter(client ec2.DescribeVolumesAPIClient, optFns ...func(*volumeAttachedDetachedWaiterOptions)) *volumeAttachedDetachedWaiter { + options := volumeAttachedDetachedWaiterOptions{} + options.MinDelay = 5 * time.Second + options.MaxDelay = 120 * time.Second + options.Retryable = volumeAttachedRetryable + options.ClientOptions = append(options.ClientOptions, func(o *ec2.Options) { + o.RetryMaxAttempts = 40 + }) + + for _, fn := range optFns { + fn(&options) + } + + return &volumeAttachedDetachedWaiter{ + client: client, + options: options, + } +} + +func volumeAttachedRetryable(ctx context.Context, input *ec2.DescribeVolumesInput, output *ec2.DescribeVolumesOutput, err error) (bool, error) { + if err != nil { + return false, err + } + + for _, volume := range output.Volumes { + for _, attachment := range volume.Attachments { + if attachment.State != ec2types.VolumeAttachmentStateAttached { + return true, nil } - req, _ := c.DescribeFastLaunchImagesRequest(inCpy) - req.SetContext(ctx) - req.ApplyOptions(opts...) - return req, nil - }, + } } - w.ApplyOptions(opts...) - return w.WaitWithContext(ctx) + return false, err +} + +func newVolumeDetachedWaiter(client ec2.DescribeVolumesAPIClient, optFns ...func(*volumeAttachedDetachedWaiterOptions)) *volumeAttachedDetachedWaiter { + options := volumeAttachedDetachedWaiterOptions{} + options.MinDelay = 5 * time.Second + options.MaxDelay = 120 * time.Second + options.Retryable = volumeDetachedRetryable + options.ClientOptions = append(options.ClientOptions, func(o *ec2.Options) { + o.RetryMaxAttempts = 40 + }) + + for _, fn := range optFns { + fn(&options) + } + + return &volumeAttachedDetachedWaiter{ + client: client, + options: options, + } +} + +func volumeDetachedRetryable(ctx context.Context, input *ec2.DescribeVolumesInput, output *ec2.DescribeVolumesOutput, err error) (bool, error) { + if err != nil { + return false, err + } + + if len(output.Volumes) == 0 { + return false, nil + } + for _, volume := range output.Volumes { + if len(volume.Attachments) > 0 { + return true, nil + } + } + + return false, err +} + +type importImageTaskWaiterOptions struct { + // Set of options to modify how an operation is invoked. These apply to all + // operations invoked for this client. Use functional options on operation call to + // modify this list for per operation behavior. + // + // Passing options here is functionally equivalent to passing values to this + // config's ClientOptions field that extend the inner client's APIOptions directly. + APIOptions []func(*middleware.Stack) error + + // Functional options to be passed to all operations invoked by this client. + // + // Function values that modify the inner APIOptions are applied after the waiter + // config's own APIOptions modifiers. + ClientOptions []func(*ec2.Options) + + // MinDelay is the minimum amount of time to delay between retries. If unset, + // VolumeInUseWaiter will use default minimum delay of 15 seconds. Note that + // MinDelay must resolve to a value lesser than or equal to the MaxDelay. + MinDelay time.Duration + + // MaxDelay is the maximum amount of time to delay between retries. If unset or + // set to zero, VolumeInUseWaiter will use default max delay of 120 seconds. Note + // that MaxDelay must resolve to value greater than or equal to the MinDelay. + MaxDelay time.Duration + + // LogWaitAttempts is used to enable logging for waiter retry attempts + LogWaitAttempts bool + + // Retryable is function that can be used to override the service defined + // waiter-behavior based on operation output, or returned error. This function is + // used by the waiter to decide if a state is retryable or a terminal state. + // + // By default service-modeled logic will populate this option. This option can + // thus be used to define a custom waiter state with fall-back to service-modeled + // waiter state mutators.The function returns an error in case of a failure state. + // In case of retry state, this function returns a bool value of true and nil + // error, while in case of success it returns a bool value of false and nil error. + Retryable func(context.Context, *ec2.DescribeImportImageTasksInput, *ec2.DescribeImportImageTasksOutput, error) (bool, error) +} + +type importImageTaskWaiter struct { + client ec2.DescribeImportImageTasksAPIClient + + options importImageTaskWaiterOptions +} + +func (w *importImageTaskWaiter) Wait(ctx context.Context, params *ec2.DescribeImportImageTasksInput, maxWaitDur time.Duration, optFns ...func(*importImageTaskWaiterOptions)) error { + if maxWaitDur <= 0 { + fmt.Errorf("maximum wait time for waiter must be greater than zero") + } + + options := w.options + for _, fn := range optFns { + fn(&options) + } + + if options.MaxDelay <= 0 { + options.MaxDelay = 120 * time.Second + } + + if options.MinDelay > options.MaxDelay { + return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) + } + + ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) + defer cancelFn() + + logger := smithywaiter.Logger{} + remainingTime := maxWaitDur + + var attempt int64 + for { + + attempt++ + apiOptions := options.APIOptions + start := time.Now() + + if options.LogWaitAttempts { + logger.Attempt = attempt + apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) + apiOptions = append(apiOptions, logger.AddLogger) + } + + out, err := w.client.DescribeImportImageTasks(ctx, params, func(o *ec2.Options) { + baseOpts := []func(*ec2.Options){ + addIsWaiterUserAgent, + } + o.APIOptions = append(o.APIOptions, apiOptions...) + for _, opt := range baseOpts { + opt(o) + } + for _, opt := range options.ClientOptions { + opt(o) + } + }) + + retryable, err := options.Retryable(ctx, params, out, err) + if err != nil { + return err + } + if !retryable { + return nil + } + + remainingTime -= time.Since(start) + if remainingTime < options.MinDelay || remainingTime <= 0 { + break + } + + // compute exponential backoff between waiter retries + delay, err := smithywaiter.ComputeDelay( + attempt, options.MinDelay, options.MaxDelay, remainingTime, + ) + if err != nil { + return fmt.Errorf("error computing waiter delay, %w", err) + } + + remainingTime -= delay + // sleep for the delay amount before invoking a request + if err := smithytime.SleepWithContext(ctx, delay); err != nil { + return fmt.Errorf("request cancelled while waiting, %w", err) + } + } + return fmt.Errorf("exceeded max wait time for ImportImageTask waiter") +} + +func newImportImageTaskWaiter(client ec2.DescribeImportImageTasksAPIClient, optFns ...func(*importImageTaskWaiterOptions)) *importImageTaskWaiter { + options := importImageTaskWaiterOptions{} + options.MinDelay = 5 * time.Second + options.MaxDelay = 120 * time.Second + options.Retryable = importImageTaskRetryable + options.ClientOptions = append(options.ClientOptions, func(o *ec2.Options) { + o.RetryMaxAttempts = 720 + }) + + for _, fn := range optFns { + fn(&options) + } + + return &importImageTaskWaiter{ + client: client, + options: options, + } +} + +func importImageTaskRetryable(ctx context.Context, input *ec2.DescribeImportImageTasksInput, output *ec2.DescribeImportImageTasksOutput, err error) (bool, error) { + if err != nil { + return false, err + } + + match := len(output.ImportImageTasks) > 0 + for _, task := range output.ImportImageTasks { + if task.Status != nil && aws.ToString(task.Status) != "completed" { + match = false + break + } + } + + if match { + return true, nil + } + + match = false + for _, task := range output.ImportImageTasks { + if task.Status != nil && aws.ToString(task.Status) == "deleted" { + match = true + break + } + } + + if match { + return false, fmt.Errorf("import image task entered failure state with status 'deleted'") + } + + return true, nil +} + +type fastLaunchImagesWaiterOptions struct { + // Set of options to modify how an operation is invoked. These apply to all + // operations invoked for this client. Use functional options on operation call to + // modify this list for per operation behavior. + // + // Passing options here is functionally equivalent to passing values to this + // config's ClientOptions field that extend the inner client's APIOptions directly. + APIOptions []func(*middleware.Stack) error + + // Functional options to be passed to all operations invoked by this client. + // + // Function values that modify the inner APIOptions are applied after the waiter + // config's own APIOptions modifiers. + ClientOptions []func(*ec2.Options) + + // MinDelay is the minimum amount of time to delay between retries. If unset, + // VolumeInUseWaiter will use default minimum delay of 15 seconds. Note that + // MinDelay must resolve to a value lesser than or equal to the MaxDelay. + MinDelay time.Duration + + // MaxDelay is the maximum amount of time to delay between retries. If unset or + // set to zero, VolumeInUseWaiter will use default max delay of 120 seconds. Note + // that MaxDelay must resolve to value greater than or equal to the MinDelay. + MaxDelay time.Duration + + // LogWaitAttempts is used to enable logging for waiter retry attempts + LogWaitAttempts bool + + // Retryable is function that can be used to override the service defined + // waiter-behavior based on operation output, or returned error. This function is + // used by the waiter to decide if a state is retryable or a terminal state. + // + // By default service-modeled logic will populate this option. This option can + // thus be used to define a custom waiter state with fall-back to service-modeled + // waiter state mutators.The function returns an error in case of a failure state. + // In case of retry state, this function returns a bool value of true and nil + // error, while in case of success it returns a bool value of false and nil error. + Retryable func(context.Context, *ec2.DescribeFastLaunchImagesInput, *ec2.DescribeFastLaunchImagesOutput, error) (bool, error) +} + +type fastLaunchImagesWaiter struct { + client ec2.DescribeFastLaunchImagesAPIClient + + options fastLaunchImagesWaiterOptions +} + +func (w *fastLaunchImagesWaiter) Wait(ctx context.Context, params *ec2.DescribeFastLaunchImagesInput, maxWaitDur time.Duration, optFns ...func(*fastLaunchImagesWaiterOptions)) error { + if maxWaitDur <= 0 { + fmt.Errorf("maximum wait time for waiter must be greater than zero") + } + + options := w.options + for _, fn := range optFns { + fn(&options) + } + + if options.MaxDelay <= 0 { + options.MaxDelay = 120 * time.Second + } + + if options.MinDelay > options.MaxDelay { + return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) + } + + ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) + defer cancelFn() + + logger := smithywaiter.Logger{} + remainingTime := maxWaitDur + + var attempt int64 + for { + + attempt++ + apiOptions := options.APIOptions + start := time.Now() + + if options.LogWaitAttempts { + logger.Attempt = attempt + apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) + apiOptions = append(apiOptions, logger.AddLogger) + } + + out, err := w.client.DescribeFastLaunchImages(ctx, params, func(o *ec2.Options) { + baseOpts := []func(*ec2.Options){ + addIsWaiterUserAgent, + } + o.APIOptions = append(o.APIOptions, apiOptions...) + for _, opt := range baseOpts { + opt(o) + } + for _, opt := range options.ClientOptions { + opt(o) + } + }) + + retryable, err := options.Retryable(ctx, params, out, err) + if err != nil { + return err + } + if !retryable { + return nil + } + + remainingTime -= time.Since(start) + if remainingTime < options.MinDelay || remainingTime <= 0 { + break + } + + // compute exponential backoff between waiter retries + delay, err := smithywaiter.ComputeDelay( + attempt, options.MinDelay, options.MaxDelay, remainingTime, + ) + if err != nil { + return fmt.Errorf("error computing waiter delay, %w", err) + } + + remainingTime -= delay + // sleep for the delay amount before invoking a request + if err := smithytime.SleepWithContext(ctx, delay); err != nil { + return fmt.Errorf("request cancelled while waiting, %w", err) + } + } + return fmt.Errorf("exceeded max wait time for ImportImageTask waiter") +} + +func newFastLaunchImageWaiter(client ec2.DescribeFastLaunchImagesAPIClient, optFns ...func(*fastLaunchImagesWaiterOptions)) *fastLaunchImagesWaiter { + options := fastLaunchImagesWaiterOptions{} + options.MinDelay = 5 * time.Second + options.MaxDelay = 120 * time.Second + options.Retryable = fastLaunchImageRetryable + options.ClientOptions = append(options.ClientOptions, func(o *ec2.Options) { + o.RetryMaxAttempts = 720 + }) + + for _, fn := range optFns { + fn(&options) + } + + return &fastLaunchImagesWaiter{ + client: client, + options: options, + } +} + +func fastLaunchImageRetryable(ctx context.Context, input *ec2.DescribeFastLaunchImagesInput, output *ec2.DescribeFastLaunchImagesOutput, err error) (bool, error) { + if err != nil { + return false, err + } + + match := len(output.FastLaunchImages) > 0 + for _, task := range output.FastLaunchImages { + if task.State != ec2types.FastLaunchStateCodeEnabled { + match = false + break + } + } + + if match { + return true, nil + } + + match = true + for _, task := range output.FastLaunchImages { + match = match && task.State == ec2types.FastLaunchStateCodeEnablingFailed + if !match { + break + } + } + + if match { + return false, fmt.Errorf("import image task entered failure state with status 'enabling-failed'") + } + + match = true + for _, task := range output.FastLaunchImages { + match = match && task.State == ec2types.FastLaunchStateCodeEnabledFailed + if !match { + break + } + } + + if match { + return false, fmt.Errorf("import image task entered failure state with status 'enabled-failed'") + } + + return false, nil } // This helper function uses the environment variables AWS_TIMEOUT_SECONDS and @@ -506,3 +915,34 @@ func applyEnvOverrides(envOverrides overridableWaitVars) []request.WaiterOption return waitOpts } + +// helper function copied from AWS SDK v2 +func addIsWaiterUserAgent(o *ec2.Options) { + o.APIOptions = append(o.APIOptions, func(stack *middleware.Stack) error { + ua, err := getOrAddRequestUserAgent(stack) + if err != nil { + return err + } + + ua.AddUserAgentFeature(awsmiddleware.UserAgentFeatureWaiter) + return nil + }) +} + +func getOrAddRequestUserAgent(stack *middleware.Stack) (*awsmiddleware.RequestUserAgent, error) { + id := (*awsmiddleware.RequestUserAgent)(nil).ID() + mw, ok := stack.Build.Get(id) + if !ok { + mw = awsmiddleware.NewRequestUserAgent() + if err := stack.Build.Add(mw, middleware.After); err != nil { + return nil, err + } + } + + ua, ok := mw.(*awsmiddleware.RequestUserAgent) + if !ok { + return nil, fmt.Errorf("%T for %s middleware did not match expected type", mw, id) + } + + return ua, nil +} diff --git a/builder/common/step_ami_region_copy.go b/builder/common/step_ami_region_copy.go index 98a0a70a..c1815d9f 100644 --- a/builder/common/step_ami_region_copy.go +++ b/builder/common/step_ami_region_copy.go @@ -8,12 +8,9 @@ import ( "fmt" "sync" - aws_v2 "github.com/aws/aws-sdk-go-v2/aws" - ec2_v2 "github.com/aws/aws-sdk-go-v2/service/ec2" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -29,7 +26,7 @@ type StepAMIRegionCopy struct { OriginalRegion string toDelete string - getRegionConn func(*AccessConfig, string) (ec2iface.EC2API, error) + getRegionConn func(context.Context, *AccessConfig, string) (clients.Ec2Client, error) AMISkipCreateImage bool AMISkipBuildRegion bool AMISnapshotCopyDurationMinutes int64 @@ -122,7 +119,7 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m wg.Add(len(s.Regions)) for _, region := range s.Regions { var regKeyID string - ui.Message(fmt.Sprintf("Copying to: %s", region)) + ui.Sayf("Copying to: %s", region) if s.EncryptBootVolume.True() { // Encrypt is true, explicitly @@ -148,7 +145,7 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m } // TODO(mitchellh): Wait but also allow for cancels to go through... - ui.Message("Waiting for all copies to complete...") + ui.Say("Waiting for all copies to complete...") wg.Wait() // If there were errors, show them @@ -163,8 +160,9 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m } func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) + ctx := state.Get("ctx").(context.Context) if len(s.toDelete) == 0 { return @@ -173,7 +171,7 @@ func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) { // Delete the unencrypted amis and snapshots ui.Say("Deregistering the AMI and deleting unencrypted temporary " + "AMIs and snapshots") - err := DestroyAMIs([]*string{&s.toDelete}, ec2conn) + err := DestroyAMIs(ctx, []string{s.toDelete}, ec2conn) if err != nil { state.Put("error", err) ui.Error(err.Error()) @@ -181,68 +179,36 @@ func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) { } } -func GetEc2Client(ctx context.Context, config *AccessConfig, target string) (*ec2_v2.Client, error) { +func GetEc2Client(ctx context.Context, config *AccessConfig, target string) (clients.Ec2Client, error) { // Connect to the region where the AMI will be copied to cfg, err := config.GetAWSConfig(ctx) if err != nil { return nil, fmt.Errorf("Error getting region connection for copy: %s", err) } //override region to the target region - cfg.Region = target - client := ec2_v2.NewFromConfig(*cfg) + client := ec2.NewFromConfig(cfg.Copy(), func(o *ec2.Options) { + o.Region = target + }) return client, nil } -func GetRegionConn(config *AccessConfig, target string) (ec2iface.EC2API, error) { - // Connect to the region where the AMI will be copied to - session, err := config.Session() - if err != nil { - return nil, fmt.Errorf("Error getting region connection for copy: %s", err) - } - - regionconn := ec2.New(session.Copy(&aws.Config{ - Region: aws.String(target), - })) - - return regionconn, nil -} - -func (s *StepAMIRegionCopy) copyImageV1(regionconn ec2iface.EC2API, name, imageId, target, source, keyId string, - encrypt *bool) (string, error) { - +func (s *StepAMIRegionCopy) copyImageV2(ctx context.Context, regionconn clients.Ec2Client, name, imageId, target, source, + keyId string, + encrypt *bool, amiSnapshotCopyDurationMinutes int64) (string, error) { var amiImageId string - t := true - resp, err := regionconn.CopyImage(&ec2.CopyImageInput{ + req := &ec2.CopyImageInput{ SourceRegion: &source, SourceImageId: &imageId, Name: &name, Encrypted: encrypt, KmsKeyId: aws.String(keyId), - CopyImageTags: &t, - }) - - if err != nil { - return "", fmt.Errorf("Error Copying AMI (%s) to region (%s): %s", - imageId, target, err) + CopyImageTags: aws.Bool(true), + } + if amiSnapshotCopyDurationMinutes > 0 { + req.SnapshotCopyCompletionDurationMinutes = aws.Int64(amiSnapshotCopyDurationMinutes) } - amiImageId = *resp.ImageId - return amiImageId, nil -} -func (s *StepAMIRegionCopy) copyImageV2(ctx context.Context, regionconn *ec2_v2.Client, name, imageId, target, source, - keyId string, - encrypt *bool, amiSnapshotCopyDurationMinutes int64) (string, error) { - var amiImageId string - t := true - resp, err := regionconn.CopyImage(ctx, &ec2_v2.CopyImageInput{ - SourceRegion: &source, - SourceImageId: &imageId, - Name: &name, - Encrypted: encrypt, - KmsKeyId: aws_v2.String(keyId), - CopyImageTags: &t, - SnapshotCopyCompletionDurationMinutes: &amiSnapshotCopyDurationMinutes, - }) + resp, err := regionconn.CopyImage(ctx, req) if err != nil { return "", fmt.Errorf("Error Copying AMI (%s) to region (%s): %s", @@ -259,31 +225,15 @@ func (s *StepAMIRegionCopy) amiRegionCopy(ctx context.Context, state multistep.S target, source, keyId string, encrypt *bool) (string, []string, error) { snapshotIds := []string{} - if s.getRegionConn == nil { - s.getRegionConn = GetRegionConn - } - regionconn, err := s.getRegionConn(config, target) + var amiImageId string + regionconn, err := GetEc2Client(ctx, config, target) if err != nil { - return "", snapshotIds, err + return "", snapshotIds, fmt.Errorf("error getting EC2 client for region (%s): %w", target, err) } - var amiImageId string - switch { - case s.AMISnapshotCopyDurationMinutes == 0: - amiImageId, err = s.copyImageV1(regionconn, name, imageId, target, source, keyId, encrypt) - if err != nil { - return "", snapshotIds, fmt.Errorf("error copying AMI (%s) to region (%s): %w", imageId, target, err) - } - default: - regionconnV2, err := GetEc2Client(ctx, config, target) - if err != nil { - return "", snapshotIds, fmt.Errorf("error getting EC2 client for region (%s): %w", target, err) - } - - amiImageId, err = s.copyImageV2(ctx, regionconnV2, name, imageId, target, source, keyId, encrypt, s.AMISnapshotCopyDurationMinutes) - if err != nil { - return "", snapshotIds, fmt.Errorf("error copying AMI (%s) to region (%s): %w", imageId, target, err) - } + amiImageId, err = s.copyImageV2(ctx, regionconn, name, imageId, target, source, keyId, encrypt, s.AMISnapshotCopyDurationMinutes) + if err != nil { + return "", snapshotIds, fmt.Errorf("error copying AMI (%s) to region (%s): %w", imageId, target, err) } // Wait for the image to become ready @@ -293,7 +243,7 @@ func (s *StepAMIRegionCopy) amiRegionCopy(ctx context.Context, state multistep.S } // Getting snapshot IDs out of the copied AMI - describeImageResp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{&amiImageId}}) + describeImageResp, err := regionconn.DescribeImages(ctx, &ec2.DescribeImagesInput{ImageIds: []string{amiImageId}}) if err != nil { return "", snapshotIds, fmt.Errorf("Error describing copied AMI (%s) in region (%s): %s", imageId, target, err) diff --git a/builder/common/step_ami_region_copy_test.go b/builder/common/step_ami_region_copy_test.go index 473bff8e..42dfa8b5 100644 --- a/builder/common/step_ami_region_copy_test.go +++ b/builder/common/step_ami_region_copy_test.go @@ -10,10 +10,10 @@ import ( "sync" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -21,7 +21,7 @@ import ( // Define a mock struct to be used in unit tests for common aws steps. type mockEC2Conn struct { - ec2iface.EC2API + clients.Ec2Client Config *aws.Config // Counters to figure out what code path was taken @@ -34,7 +34,7 @@ type mockEC2Conn struct { lock sync.Mutex } -func (m *mockEC2Conn) CopyImage(copyInput *ec2.CopyImageInput) (*ec2.CopyImageOutput, error) { +func (m *mockEC2Conn) CopyImage(ctx context.Context, copyInput *ec2.CopyImageInput, opts ...func(*ec2.Options)) (*ec2.CopyImageOutput, error) { if !*copyInput.CopyImageTags { return nil, fmt.Errorf("CopyImageTags should always be true, but was %t", *copyInput.CopyImageTags) } @@ -49,17 +49,17 @@ func (m *mockEC2Conn) CopyImage(copyInput *ec2.CopyImageInput) (*ec2.CopyImageOu } // functions we have to create mock responses for in order for test to run -func (m *mockEC2Conn) DescribeImages(*ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error) { +func (m *mockEC2Conn) DescribeImages(ctx context.Context, input *ec2.DescribeImagesInput, opts ...func(*ec2.Options)) (*ec2.DescribeImagesOutput, error) { m.lock.Lock() m.describeImagesCount++ m.lock.Unlock() output := &ec2.DescribeImagesOutput{ - Images: []*ec2.Image{{}}, + Images: []ec2types.Image{{}}, } return output, nil } -func (m *mockEC2Conn) DeregisterImage(*ec2.DeregisterImageInput) (*ec2.DeregisterImageOutput, error) { +func (m *mockEC2Conn) DeregisterImage(ctx context.Context, input *ec2.DeregisterImageInput, opts ...func(*ec2.Options)) (*ec2.DeregisterImageOutput, error) { m.lock.Lock() m.deregisterImageCount++ m.lock.Unlock() @@ -67,7 +67,7 @@ func (m *mockEC2Conn) DeregisterImage(*ec2.DeregisterImageInput) (*ec2.Deregiste return output, nil } -func (m *mockEC2Conn) DeleteSnapshot(*ec2.DeleteSnapshotInput) (*ec2.DeleteSnapshotOutput, error) { +func (m *mockEC2Conn) DeleteSnapshot(ctx context.Context, input *ec2.DeleteSnapshotInput, opts ...func(*ec2.Options)) (*ec2.DeleteSnapshotOutput, error) { m.lock.Lock() m.deleteSnapshotCount++ m.lock.Unlock() @@ -75,23 +75,31 @@ func (m *mockEC2Conn) DeleteSnapshot(*ec2.DeleteSnapshotInput) (*ec2.DeleteSnaps return output, nil } +// we don't need to mock out the waiter +/* func (m *mockEC2Conn) WaitUntilImageAvailableWithContext(aws.Context, *ec2.DescribeImagesInput, ...request.WaiterOption) error { m.lock.Lock() m.waitCount++ m.lock.Unlock() return nil } +*/ -func getMockConn(config *AccessConfig, target string) (ec2iface.EC2API, error) { +func getMockConn(ctx context.Context, config *AccessConfig, target string) (clients.Ec2Client, error) { + awscfg, err := config.GetAWSConfig(ctx) + if err != nil { + return nil, fmt.Errorf("Error getting region connection for copy: %s", err) + } + awscfg.Region = target mockConn := &mockEC2Conn{ - Config: aws.NewConfig(), + Config: awscfg, } return mockConn, nil } // Create statebag for running test -func tState() multistep.StateBag { +func tState(ctx context.Context) multistep.StateBag { state := new(multistep.BasicStateBag) state.Put("ui", &packersdk.BasicUi{ Reader: new(bytes.Buffer), @@ -99,7 +107,7 @@ func tState() multistep.StateBag { }) state.Put("amis", map[string]string{"us-east-1": "ami-12345"}) state.Put("snapshots", map[string][]string{"us-east-1": {"snap-0012345"}}) - conn, _ := getMockConn(&AccessConfig{}, "us-east-2") + conn, _ := getMockConn(ctx, &AccessConfig{}, "us-east-2") state.Put("ec2", conn) return state } @@ -123,9 +131,10 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn - state := tState() + ctx := t.Context() + state := tState(ctx) state.Put("intermediary_image", true) - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if len(stepAMIRegionCopy.Regions) != 1 { t.Fatalf("Should have added original ami to Regions one time only") @@ -145,7 +154,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) { // mock out the region connection code state.Put("intermediary_image", false) stepAMIRegionCopy.getRegionConn = getMockConn - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if len(stepAMIRegionCopy.Regions) != 0 { t.Fatalf("Should not have added original ami to Regions; not encrypting") @@ -167,7 +176,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) { // mock out the region connection code state.Put("intermediary_image", false) stepAMIRegionCopy.getRegionConn = getMockConn - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if len(stepAMIRegionCopy.Regions) != 0 { t.Fatalf("Should not have added original ami to Regions once; not" + @@ -193,7 +202,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn state.Put("intermediary_image", true) - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if len(stepAMIRegionCopy.Regions) != 3 { t.Fatalf("Each AMI should have been added to Regions one time only.") @@ -218,7 +227,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn state.Put("intermediary_image", false) - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if len(stepAMIRegionCopy.Regions) != 2 { t.Fatalf("Each AMI should have been added to Regions one time only, " + @@ -240,9 +249,10 @@ func TestStepAmiRegionCopy_nil_encryption(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn - state := tState() + ctx := t.Context() + state := tState(ctx) state.Put("intermediary_image", false) - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete != "" { t.Fatalf("Shouldn't have an intermediary ami if encrypt is nil") @@ -266,9 +276,10 @@ func TestStepAmiRegionCopy_true_encryption(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn - state := tState() + ctx := t.Context() + state := tState(ctx) state.Put("intermediary_image", true) - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete == "" { t.Fatalf("Should delete original AMI if encrypted=true") @@ -292,8 +303,9 @@ func TestStepAmiRegionCopy_nil_intermediary(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn - state := tState() - stepAMIRegionCopy.Run(context.Background(), state) + ctx := t.Context() + state := tState(ctx) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete != "" { t.Fatalf("Should not delete original AMI if no intermediary") @@ -320,9 +332,10 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) { // mock out the region connection code stepAMIRegionCopy.getRegionConn = getMockConn - state := tState() + ctx := t.Context() + state := tState(ctx) state.Put("intermediary_image", true) - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete == "" { t.Fatalf("Should delete original AMI if skip_save_build_region=true") @@ -347,7 +360,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) { stepAMIRegionCopy.getRegionConn = getMockConn state.Put("intermediary_image", false) // not encrypted - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete != "" { t.Fatalf("Shouldn't have an intermediary AMI, so dont delete original ami") @@ -373,7 +386,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) { stepAMIRegionCopy.getRegionConn = getMockConn state.Put("intermediary_image", true) //encrypted - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete == "" { t.Fatalf("Have to delete intermediary AMI") @@ -399,7 +412,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) { stepAMIRegionCopy.getRegionConn = getMockConn state.Put("intermediary_image", true) //encrypted - stepAMIRegionCopy.Run(context.Background(), state) + stepAMIRegionCopy.Run(ctx, state) if stepAMIRegionCopy.toDelete == "" { t.Fatalf("Have to delete intermediary AMI") diff --git a/builder/common/step_create_ssm_tunnel.go b/builder/common/step_create_ssm_tunnel.go index 5bec885d..da15475d 100644 --- a/builder/common/step_create_ssm_tunnel.go +++ b/builder/common/step_create_ssm_tunnel.go @@ -10,12 +10,12 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2instanceconnect" - "github.com/aws/aws-sdk-go/service/ssm" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect" + "github.com/aws/aws-sdk-go-v2/service/ssm" pssm "github.com/hashicorp/packer-plugin-amazon/builder/common/ssm" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/communicator/sshkey" "github.com/hashicorp/packer-plugin-sdk/multistep" @@ -24,7 +24,7 @@ import ( ) type StepCreateSSMTunnel struct { - AWSSession *session.Session + AwsConfig aws.Config Region string LocalPortNumber int RemotePortNumber int @@ -37,7 +37,7 @@ type StepCreateSSMTunnel struct { // Run executes the Packer build step that creates a session tunnel. func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packersdk.Ui) - + awscfg := state.Get("awsConfig").(*aws.Config) if !s.SSMAgentEnabled { return multistep.ActionContinue } @@ -62,7 +62,7 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) } // Get instance information - instance, ok := state.Get("instance").(*ec2.Instance) + instance, ok := state.Get("instance").(*ec2types.Instance) if !ok { err := fmt.Errorf("error encountered in obtaining target instance id for session tunnel") ui.Error(err.Error()) @@ -74,12 +74,12 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) ssmCtx, ssmCancel := context.WithCancel(ctx) s.stopSSMCommand = ssmCancel - ec2Conn := state.Get("ec2").(*ec2.EC2) + ec2Conn := state.Get("ec2").(clients.Ec2Client) - ssmconn := ssm.New(s.AWSSession) + ssmconn := ssm.NewFromConfig(awscfg.Copy()) session := pssm.Session{ SvcClient: ssmconn, - InstanceID: aws.StringValue(instance.InstanceId), + InstanceID: aws.ToString(instance.InstanceId), RemotePort: s.RemotePortNumber, LocalPort: s.LocalPortNumber, Region: s.Region, @@ -90,7 +90,7 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) return multistep.ActionContinue } -func (s *StepCreateSSMTunnel) CreatePersistentSSMSession(ctx context.Context, ui packersdk.Ui, session *pssm.Session, instance *ec2.Instance) { +func (s *StepCreateSSMTunnel) CreatePersistentSSMSession(ctx context.Context, ui packersdk.Ui, session *pssm.Session, instance *ec2types.Instance) { sessionChan := make(chan struct{}) go func() { @@ -99,7 +99,7 @@ func (s *StepCreateSSMTunnel) CreatePersistentSSMSession(ctx context.Context, ui for range sessionChan { if len(s.SSHConfig.SSHPrivateKey) != 0 && s.SSHConfig.SSHKeyPairName == "" { ui.Say("Uploading SSH public key to instance") - err := s.sendUserSSHPublicKey(instance, s.SSHConfig.SSHPrivateKey) + err := s.sendUserSSHPublicKey(ctx, instance, s.SSHConfig.SSHPrivateKey) if err != nil { ui.Error(err.Error()) } @@ -114,14 +114,15 @@ func (s *StepCreateSSMTunnel) CreatePersistentSSMSession(ctx context.Context, ui } func (s *StepCreateSSMTunnel) sendUserSSHPublicKey( - instance *ec2.Instance, + ctx context.Context, + instance *ec2types.Instance, privateKey []byte, ) error { publicKey, err := sshkey.PublicKeyFromPrivate(privateKey) if err != nil { return fmt.Errorf("Error getting public key from private key: %s", err) } - svc := ec2instanceconnect.New(s.AWSSession) + svc := ec2instanceconnect.NewFromConfig(s.AwsConfig) input := &ec2instanceconnect.SendSSHPublicKeyInput{ AvailabilityZone: aws.String(*instance.Placement.AvailabilityZone), InstanceId: aws.String(*instance.InstanceId), @@ -129,7 +130,7 @@ func (s *StepCreateSSMTunnel) sendUserSSHPublicKey( SSHPublicKey: aws.String(strings.TrimSuffix(string(publicKey), "\n")), } log.Printf("Sending public key to instance: %s", *input.InstanceId) - result, err := svc.SendSSHPublicKey(input) + result, err := svc.SendSSHPublicKey(ctx, input) if err != nil { err := fmt.Errorf(` error encountered in sending public key to instance: %s @@ -137,7 +138,7 @@ func (s *StepCreateSSMTunnel) sendUserSSHPublicKey( https://docs.aws.amazon.com/ec2-instance-connect/latest/APIReference/API_SendSSHPublicKey.html`, err) return err } else { - if *result.Success { + if result.Success { return nil } } diff --git a/builder/common/step_create_tags.go b/builder/common/step_create_tags.go index e705ce12..0ab88054 100644 --- a/builder/common/step_create_tags.go +++ b/builder/common/step_create_tags.go @@ -8,9 +8,8 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -27,8 +26,7 @@ type StepCreateTags struct { } func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) - session := state.Get("awsSession").(*session.Session) + awscfg := state.Get("awsConfig").(*aws.Config) ui := state.Get("ui").(packersdk.Ui) if s.AMISkipCreateImage { @@ -46,13 +44,13 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult for region, ami := range amis { ui.Say(fmt.Sprintf("Adding tags to AMI (%s)...", ami)) - regionConn := ec2.New(session, &aws.Config{ - Region: aws.String(region), + regionConn := ec2.NewFromConfig(*awscfg, func(o *ec2.Options) { + o.Region = region }) // Retrieve image list for given AMI - resourceIds := []*string{&ami} - imageResp, err := regionConn.DescribeImages(&ec2.DescribeImagesInput{ + resourceIds := []string{ami} + imageResp, err := regionConn.DescribeImages(ctx, &ec2.DescribeImagesInput{ ImageIds: resourceIds, }) @@ -71,20 +69,20 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult } image := imageResp.Images[0] - snapshotIds := []*string{} + snapshotIds := []string{} // Add only those with a Snapshot ID, i.e. not Ephemeral for _, device := range image.BlockDeviceMappings { if device.Ebs != nil && device.Ebs.SnapshotId != nil { ui.Say(fmt.Sprintf("Tagging snapshot: %s", *device.Ebs.SnapshotId)) - resourceIds = append(resourceIds, device.Ebs.SnapshotId) - snapshotIds = append(snapshotIds, device.Ebs.SnapshotId) + resourceIds = append(resourceIds, aws.ToString(device.Ebs.SnapshotId)) + snapshotIds = append(snapshotIds, aws.ToString(device.Ebs.SnapshotId)) } } // Convert tags to ec2.Tag format ui.Say("Creating AMI tags") - amiTags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + amiTags, err := TagMap(s.Tags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { state.Put("error", err) ui.Error(err.Error()) @@ -93,7 +91,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult amiTags.Report(ui) ui.Say("Creating snapshot tags") - snapshotTags, err := TagMap(s.SnapshotTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + snapshotTags, err := TagMap(s.SnapshotTags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { state.Put("error", err) ui.Error(err.Error()) @@ -114,7 +112,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult var err error if len(amiTags) > 0 { - _, err = regionConn.CreateTags(&ec2.CreateTagsInput{ + _, err = regionConn.CreateTags(ctx, &ec2.CreateTagsInput{ Resources: resourceIds, Tags: amiTags, }) @@ -125,7 +123,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult // Override tags on snapshots if len(snapshotTags) > 0 { - _, err = regionConn.CreateTags(&ec2.CreateTagsInput{ + _, err = regionConn.CreateTags(ctx, &ec2.CreateTagsInput{ Resources: snapshotIds, Tags: snapshotTags, }) diff --git a/builder/common/step_deregister_ami.go b/builder/common/step_deregister_ami.go index e63e37ef..45b4b1cb 100644 --- a/builder/common/step_deregister_ami.go +++ b/builder/common/step_deregister_ami.go @@ -7,8 +7,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -28,26 +29,27 @@ func (s *StepDeregisterAMI) Run(ctx context.Context, state multistep.StateBag) m } ui := state.Get("ui").(packersdk.Ui) - ec2conn := state.Get("ec2").(*ec2.EC2) + awscfg, err := s.AccessConfig.GetAWSConfig(ctx) + if err != nil { + err := fmt.Errorf("error getting AWS config: %w", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } // Add the session region to list of regions will deregister AMIs in - regions := append(s.Regions, *ec2conn.Config.Region) + regions := append(s.Regions, awscfg.Region) for _, region := range regions { // get new connection for each region in which we need to deregister vms - session, err := s.AccessConfig.Session() - if err != nil { - return multistep.ActionHalt - } - - regionconn := ec2.New(session.Copy(&aws.Config{ - Region: aws.String(region), - })) + regionconn := ec2.NewFromConfig(awscfg.Copy(), func(o *ec2.Options) { + o.Region = region + }) - resp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{ - Owners: aws.StringSlice([]string{"self"}), - Filters: []*ec2.Filter{{ + resp, err := regionconn.DescribeImages(ctx, &ec2.DescribeImagesInput{ + Owners: []string{"self"}, + Filters: []ec2types.Filter{{ Name: aws.String("name"), - Values: aws.StringSlice([]string{s.AMIName}), + Values: []string{s.AMIName}, }}}) if err != nil { @@ -59,7 +61,7 @@ func (s *StepDeregisterAMI) Run(ctx context.Context, state multistep.StateBag) m // Deregister image(s) by name for _, i := range resp.Images { - _, err := regionconn.DeregisterImage(&ec2.DeregisterImageInput{ + _, err := regionconn.DeregisterImage(ctx, &ec2.DeregisterImageInput{ ImageId: i.ImageId, }) @@ -69,13 +71,13 @@ func (s *StepDeregisterAMI) Run(ctx context.Context, state multistep.StateBag) m ui.Error(err.Error()) return multistep.ActionHalt } - ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageId)) + ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, aws.ToString(i.ImageId))) // Delete snapshot(s) by image if s.ForceDeleteSnapshot { for _, b := range i.BlockDeviceMappings { - if b.Ebs != nil && aws.StringValue(b.Ebs.SnapshotId) != "" { - _, err := regionconn.DeleteSnapshot(&ec2.DeleteSnapshotInput{ + if b.Ebs != nil && aws.ToString(b.Ebs.SnapshotId) != "" { + _, err := regionconn.DeleteSnapshot(ctx, &ec2.DeleteSnapshotInput{ SnapshotId: b.Ebs.SnapshotId, }) @@ -85,7 +87,7 @@ func (s *StepDeregisterAMI) Run(ctx context.Context, state multistep.StateBag) m ui.Error(err.Error()) return multistep.ActionHalt } - ui.Say(fmt.Sprintf("Deleted snapshot: %s", *b.Ebs.SnapshotId)) + ui.Say(fmt.Sprintf("Deleted snapshot: %s", aws.ToString(b.Ebs.SnapshotId))) } } } diff --git a/builder/common/step_enable_deprecation.go b/builder/common/step_enable_deprecation.go index b40d6e81..49f655d7 100644 --- a/builder/common/step_enable_deprecation.go +++ b/builder/common/step_enable_deprecation.go @@ -8,7 +8,7 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -38,7 +38,7 @@ func (s *StepEnableDeprecation) Run(ctx context.Context, state multistep.StateBa for region, ami := range amis { ui.Say(fmt.Sprintf("Enabling deprecation on AMI (%s) in region %q ...", ami, region)) - conn, err := GetRegionConn(s.AccessConfig, region) + conn, err := GetRegionConn(ctx, s.AccessConfig, region) if err != nil { err := fmt.Errorf("failed to connect to region %s: %s", region, err) state.Put("error", err.Error()) diff --git a/builder/common/step_key_pair.go b/builder/common/step_key_pair.go index d02f9575..74efe054 100644 --- a/builder/common/step_key_pair.go +++ b/builder/common/step_key_pair.go @@ -12,7 +12,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -63,7 +63,7 @@ func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multist return multistep.ActionContinue } - ec2conn := state.Get("ec2").(ec2iface.EC2API) + ec2conn := state.Get("ec2").(clients.Ec2Client) var keyResp *ec2.CreateKeyPairOutput ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.Comm.SSHTemporaryKeyPairName)) diff --git a/builder/common/step_key_pair_test.go b/builder/common/step_key_pair_test.go index e3efe488..37c59bc2 100644 --- a/builder/common/step_key_pair_test.go +++ b/builder/common/step_key_pair_test.go @@ -11,14 +11,14 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) type mockEC2KeyPairConn struct { - ec2iface.EC2API + clients.Ec2Client CreateKeyPairCount int CreateKeyPairArgs []ec2.CreateKeyPairInput @@ -38,7 +38,7 @@ func (m *mockEC2KeyPairConn) CreateKeyPair(keyPairInput *ec2.CreateKeyPairInput) return output, nil } -func getKeyPairMockConn() ec2iface.EC2API { +func getKeyPairMockConn() clients.Ec2Client { return &mockEC2KeyPairConn{} } diff --git a/builder/common/step_modify_ami_attributes.go b/builder/common/step_modify_ami_attributes.go index 9ab3a49b..4fdfd7ea 100644 --- a/builder/common/step_modify_ami_attributes.go +++ b/builder/common/step_modify_ami_attributes.go @@ -7,9 +7,11 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata" @@ -26,7 +28,7 @@ type StepModifyAMIAttributes struct { SnapshotUsers []string SnapshotGroups []string ProductCodes []string - IMDSSupport string + IMDSSupport ec2types.ImdsSupportValues Description string Ctx interpolate.Context @@ -34,9 +36,10 @@ type StepModifyAMIAttributes struct { } func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) session := state.Get("awsSession").(*session.Session) ui := state.Get("ui").(packersdk.Ui) + config := state.Get("config").(*Config) if s.AMISkipCreateImage { ui.Say("Skipping AMI modify attributes...") diff --git a/builder/common/step_modify_ebs_instance.go b/builder/common/step_modify_ebs_instance.go index 07304a57..b05e6c17 100644 --- a/builder/common/step_modify_ebs_instance.go +++ b/builder/common/step_modify_ebs_instance.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -22,7 +22,7 @@ type StepModifyEBSBackedInstance struct { } func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(ec2iface.EC2API) + ec2conn := state.Get("ec2").(clients.Ec2Client) instance := state.Get("instance").(*ec2.Instance) ui := state.Get("ui").(packersdk.Ui) diff --git a/builder/common/step_network_info.go b/builder/common/step_network_info.go index 05f33d3d..946d7a19 100644 --- a/builder/common/step_network_info.go +++ b/builder/common/step_network_info.go @@ -10,9 +10,10 @@ import ( "math/rand" "sort" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -38,10 +39,10 @@ type StepNetworkInfo struct { // RequestedMachineType is the machine type of the instance we want to create. // This is used for selecting a subnet/AZ which supports the type of instance // selected, and not just the most available / random one. - RequestedMachineType string + RequestedMachineType ec2types.InstanceType } -type subnetsSort []*ec2.Subnet +type subnetsSort []ec2types.Subnet func (a subnetsSort) Len() int { return len(a) } func (a subnetsSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } @@ -50,14 +51,14 @@ func (a subnetsSort) Less(i, j int) bool { } // Returns the most recent AMI out of a slice of images. -func mostFreeSubnet(subnets []*ec2.Subnet) *ec2.Subnet { +func mostFreeSubnet(subnets []ec2types.Subnet) ec2types.Subnet { sortedSubnets := subnets sort.Sort(subnetsSort(sortedSubnets)) return sortedSubnets[len(sortedSubnets)-1] } func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(ec2iface.EC2API) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) // Set VpcID if none was specified but filters are defined in the template. @@ -75,7 +76,7 @@ func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) mul log.Printf("Using VPC Filters %v", params) - vpcResp, err := ec2conn.DescribeVpcs(params) + vpcResp, err := ec2conn.DescribeVpcs(ctx, params) if err != nil { err := fmt.Errorf("Error querying VPCs: %s", err) state.Put("error", err) @@ -115,7 +116,7 @@ func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) mul params.Filters = subnetFilters log.Printf("Using Subnet Filters %v", params) - subnetsResp, err := ec2conn.DescribeSubnets(params) + subnetsResp, err := ec2conn.DescribeSubnets(ctx, params) if err != nil { err := fmt.Errorf("Error querying Subnets: %s", err) state.Put("error", err) @@ -137,7 +138,7 @@ func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) mul return multistep.ActionHalt } - var subnet *ec2.Subnet + var subnet ec2types.Subnet switch { case s.SubnetFilter.MostFree: subnet = mostFreeSubnet(subnetsResp.Subnets) @@ -153,7 +154,7 @@ func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) mul // Set VPC/Subnet if we explicitely enable or disable public IP assignment to the instance // and we did not set or get a subnet ID before if s.AssociatePublicIpAddress != config.TriUnset && s.SubnetId == "" { - err := s.GetDefaultVPCAndSubnet(ui, ec2conn, state) + err := s.GetDefaultVPCAndSubnet(ctx, ui, ec2conn, state) if err != nil { ui.Say("associate_public_ip_address is set without a subnet_id.") ui.Say(fmt.Sprintf("Packer attempted to infer a subnet from default VPC (if unspecified), but failed due to: %s", err)) @@ -164,7 +165,7 @@ func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) mul // Try to find AZ and VPC Id from Subnet if they are not yet found/given if s.SubnetId != "" && (s.AvailabilityZone == "" || s.VpcId == "") { log.Printf("[INFO] Finding AZ and VpcId for the given subnet '%s'", s.SubnetId) - resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&s.SubnetId}}) + resp, err := ec2conn.DescribeSubnets(ctx, &ec2.DescribeSubnetsInput{SubnetIds: []string{s.SubnetId}}) if err != nil { err := fmt.Errorf("Describing the subnet: %s returned error: %s.", s.SubnetId, err) state.Put("error", err) @@ -187,18 +188,18 @@ func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) mul return multistep.ActionContinue } -func (s *StepNetworkInfo) GetDefaultVPCAndSubnet(ui packersdk.Ui, ec2conn ec2iface.EC2API, state multistep.StateBag) error { +func (s *StepNetworkInfo) GetDefaultVPCAndSubnet(ctx context.Context, ui packersdk.Ui, ec2conn clients.Ec2Client, state multistep.StateBag) error { ui.Say(fmt.Sprintf("Setting public IP address to %t on instance without a subnet ID", *s.AssociatePublicIpAddress.ToBoolPointer())) var vpc = s.VpcId if vpc == "" { ui.Say("No VPC ID provided, Packer will use the default VPC") - vpcs, err := ec2conn.DescribeVpcs(&ec2.DescribeVpcsInput{ - Filters: []*ec2.Filter{ + vpcs, err := ec2conn.DescribeVpcs(ctx, &ec2.DescribeVpcsInput{ + Filters: []ec2types.Filter{ { Name: aws.String("is-default"), - Values: []*string{aws.String("true")}, + Values: []string{"true"}, }, }, }) @@ -224,7 +225,7 @@ func (s *StepNetworkInfo) GetDefaultVPCAndSubnet(ui packersdk.Ui, ec2conn ec2ifa if err != nil { return fmt.Errorf("Failed to prepare subnet filters: %s", err) } - subnetOut, err := ec2conn.DescribeSubnets(params) + subnetOut, err := ec2conn.DescribeSubnets(ctx, params) if err != nil { return fmt.Errorf("Failed to describe subnets: %s", err) } @@ -233,7 +234,7 @@ func (s *StepNetworkInfo) GetDefaultVPCAndSubnet(ui packersdk.Ui, ec2conn ec2ifa // Filter by AZ with support for machine type azs := getAZFromSubnets(subnets) - azs, err = filterAZByMachineType(azs, s.RequestedMachineType, ec2conn) + azs, err = filterAZByMachineType(ctx, azs, s.RequestedMachineType, ec2conn) if err == nil { subnets = filterSubnetsByAZ(subnets, azs) if subnets == nil { @@ -258,7 +259,7 @@ func (s *StepNetworkInfo) GetDefaultVPCAndSubnet(ui packersdk.Ui, ec2conn ec2ifa return nil } -func getAZFromSubnets(subnets []*ec2.Subnet) []string { +func getAZFromSubnets(subnets []ec2types.Subnet) []string { azs := map[string]struct{}{} for _, sub := range subnets { azs[*sub.AvailabilityZone] = struct{}{} @@ -272,20 +273,20 @@ func getAZFromSubnets(subnets []*ec2.Subnet) []string { return retAZ } -func filterAZByMachineType(azs []string, machineType string, ec2conn ec2iface.EC2API) ([]string, error) { +func filterAZByMachineType(ctx context.Context, azs []string, machineType ec2types.InstanceType, ec2conn clients.Ec2Client) ([]string, error) { var retAZ []string for _, az := range azs { - resp, err := ec2conn.DescribeInstanceTypeOfferings(&ec2.DescribeInstanceTypeOfferingsInput{ - LocationType: aws.String("availability-zone"), - Filters: []*ec2.Filter{ + resp, err := ec2conn.DescribeInstanceTypeOfferings(ctx, &ec2.DescribeInstanceTypeOfferingsInput{ + LocationType: ec2types.LocationTypeAvailabilityZone, + Filters: []ec2types.Filter{ { Name: aws.String("location"), - Values: []*string{&az}, + Values: []string{az}, }, { Name: aws.String("instance-type"), - Values: []*string{&machineType}, + Values: []string{string(machineType)}, }, }, }) @@ -295,7 +296,7 @@ func filterAZByMachineType(azs []string, machineType string, ec2conn ec2iface.EC } for _, off := range resp.InstanceTypeOfferings { - if *off.InstanceType == machineType { + if off.InstanceType == machineType { retAZ = append(retAZ, az) break } @@ -309,8 +310,8 @@ func filterAZByMachineType(azs []string, machineType string, ec2conn ec2iface.EC return retAZ, nil } -func filterSubnetsByAZ(subnets []*ec2.Subnet, azs []string) []*ec2.Subnet { - var retSubs []*ec2.Subnet +func filterSubnetsByAZ(subnets []ec2types.Subnet, azs []string) []ec2types.Subnet { + var retSubs []ec2types.Subnet outLoop: for _, sub := range subnets { diff --git a/builder/common/step_network_info_test.go b/builder/common/step_network_info_test.go index 492ead81..b25ba86a 100644 --- a/builder/common/step_network_info_test.go +++ b/builder/common/step_network_info_test.go @@ -11,15 +11,15 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" confighelper "github.com/hashicorp/packer-plugin-sdk/template/config" ) type mockEC2ClientStepNetworkTests struct { - ec2iface.EC2API + clients.Ec2Client describeInstanceTypeOfferings func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) describeVpcs func(*ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) diff --git a/builder/common/step_pre_validate.go b/builder/common/step_pre_validate.go index 7b2a2e43..3086b443 100644 --- a/builder/common/step_pre_validate.go +++ b/builder/common/step_pre_validate.go @@ -11,8 +11,8 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/retry" @@ -131,7 +131,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul return multistep.ActionContinue } -func (s *StepPreValidate) checkVpc(conn ec2iface.EC2API) error { +func (s *StepPreValidate) checkVpc(conn clients.Ec2Client) error { if s.VpcId == "" || (s.VpcId != "" && (s.SubnetId != "" || s.HasSubnetFilter)) { // Skip validation if: // * The user has not provided a VpcId. diff --git a/builder/common/step_pre_validate_test.go b/builder/common/step_pre_validate_test.go index be66dbc4..4d797d60 100644 --- a/builder/common/step_pre_validate_test.go +++ b/builder/common/step_pre_validate_test.go @@ -4,23 +4,25 @@ package common import ( + "context" "fmt" "strings" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) // DescribeVpcs mocks an ec2.DescribeVpcsOutput for a given input -func (m *mockEC2Conn) DescribeVpcs(input *ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) { +func (m *mockEC2Conn) DescribeVpcs(ctx context.Context, input *ec2.DescribeVpcsInput, opts ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) { - if input == nil || aws.StringValue(input.VpcIds[0]) == "" { + if input == nil || input.VpcIds[0] == "" { return nil, fmt.Errorf("oops looks like we need more input") } var isDefault bool - vpcID := aws.StringValue(input.VpcIds[0]) + vpcID := input.VpcIds[0] //only one default VPC per region if strings.Contains("vpc-default-id", vpcID) { @@ -28,7 +30,7 @@ func (m *mockEC2Conn) DescribeVpcs(input *ec2.DescribeVpcsInput) (*ec2.DescribeV } output := &ec2.DescribeVpcsOutput{ - Vpcs: []*ec2.Vpc{ + Vpcs: []ec2types.Vpc{ {IsDefault: aws.Bool(isDefault), VpcId: aws.String(vpcID), }, diff --git a/builder/common/step_run_source_instance.go b/builder/common/step_run_source_instance.go index f1fd83df..c85786dc 100644 --- a/builder/common/step_run_source_instance.go +++ b/builder/common/step_run_source_instance.go @@ -11,11 +11,12 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -28,7 +29,7 @@ type StepRunSourceInstance struct { PollingConfig *AWSPollingConfig AssociatePublicIpAddress config.Trilean LaunchMappings EC2BlockDeviceMappingsBuilder - CapacityReservationPreference string + CapacityReservationPreference ec2types.CapacityReservationPreference CapacityReservationId string CapacityReservationGroupArn string Comm *communicator.Config @@ -36,20 +37,20 @@ type StepRunSourceInstance struct { Debug bool EbsOptimized bool EnableUnlimitedCredits bool - ExpectedRootDevice string - HttpEndpoint string - HttpTokens string - HttpPutResponseHopLimit int64 - InstanceMetadataTags string - InstanceInitiatedShutdownBehavior string - InstanceType string + ExpectedRootDevice ec2types.DeviceType + HttpEndpoint ec2types.InstanceMetadataEndpointState + HttpTokens ec2types.HttpTokensState + HttpPutResponseHopLimit int32 + InstanceMetadataTags ec2types.InstanceMetadataTagsState + InstanceInitiatedShutdownBehavior ec2types.ShutdownBehavior + InstanceType ec2types.InstanceType IsRestricted bool SourceAMI string Tags map[string]string LicenseSpecifications []LicenseSpecification HostResourceGroupArn string HostId string - Tenancy string + Tenancy ec2types.Tenancy UserData string UserDataFile string VolumeTags map[string]string @@ -61,9 +62,9 @@ type StepRunSourceInstance struct { } func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) - - securityGroupIds := aws.StringSlice(state.Get("securityGroupIds").([]string)) + ec2conn := state.Get("ec2").(clients.Ec2Client) + awscfg := state.Get("awsConfig").(*aws.Config) + securityGroupIds := state.Get("securityGroupIds").([]string) iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string)) ui := state.Get("ui").(packersdk.Ui) @@ -86,24 +87,24 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } ui.Say("Launching a source AWS instance...") - image, ok := state.Get("source_image").(*ec2.Image) + image, ok := state.Get("source_image").(*ec2types.Image) if !ok { state.Put("error", fmt.Errorf("source_image type assertion failed")) return multistep.ActionHalt } s.SourceAMI = *image.ImageId - if s.ExpectedRootDevice != "" && *image.RootDeviceType != s.ExpectedRootDevice { + if s.ExpectedRootDevice != "" && image.RootDeviceType != s.ExpectedRootDevice { state.Put("error", fmt.Errorf( "The provided source AMI has an invalid root device type.\n"+ "Expected '%s', got '%s'.", - s.ExpectedRootDevice, *image.RootDeviceType)) + s.ExpectedRootDevice, image.RootDeviceType)) return multistep.ActionHalt } var instanceId string - ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { err := fmt.Errorf("Error tagging source instance: %s", err) state.Put("error", err) @@ -111,7 +112,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa return multistep.ActionHalt } - volTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + volTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { err := fmt.Errorf("Error tagging volumes: %s", err) state.Put("error", err) @@ -119,20 +120,20 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa return multistep.ActionHalt } - enclaveOptions := ec2.EnclaveOptionsRequest{ + enclaveOptions := ec2types.EnclaveOptionsRequest{ Enabled: &s.EnableNitroEnclave, } az := state.Get("availability_zone").(string) runOpts := &ec2.RunInstancesInput{ ImageId: &s.SourceAMI, - InstanceType: &s.InstanceType, + InstanceType: s.InstanceType, UserData: &userData, - MaxCount: aws.Int64(1), - MinCount: aws.Int64(1), - IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: iamInstanceProfile}, + MaxCount: aws.Int32(1), + MinCount: aws.Int32(1), + IamInstanceProfile: &ec2types.IamInstanceProfileSpecification{Name: iamInstanceProfile}, BlockDeviceMappings: s.LaunchMappings.BuildEC2BlockDeviceMappings(), - Placement: &ec2.Placement{AvailabilityZone: &az}, + Placement: &ec2types.Placement{AvailabilityZone: &az}, EbsOptimized: &s.EbsOptimized, EnclaveOptions: &enclaveOptions, } @@ -148,7 +149,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings") DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz" for _, letter := range DefaultEphemeralDeviceLetters { - bd := &ec2.BlockDeviceMapping{ + bd := ec2types.BlockDeviceMapping{ DeviceName: aws.String("xvdc" + string(letter)), NoDevice: aws.String(""), } @@ -157,38 +158,38 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } if s.IsBurstableInstanceType { - runOpts.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsStandard)} + runOpts.CreditSpecification = &ec2types.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsStandard)} } if s.EnableUnlimitedCredits { - runOpts.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsUnlimited)} + runOpts.CreditSpecification = &ec2types.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsUnlimited)} } - if s.HttpEndpoint == "enabled" { - runOpts.MetadataOptions = &ec2.InstanceMetadataOptionsRequest{ - HttpEndpoint: &s.HttpEndpoint, - HttpTokens: &s.HttpTokens, - HttpPutResponseHopLimit: &s.HttpPutResponseHopLimit, + if s.HttpEndpoint == ec2types.InstanceMetadataEndpointStateEnabled { + runOpts.MetadataOptions = &ec2types.InstanceMetadataOptionsRequest{ + HttpEndpoint: s.HttpEndpoint, + HttpTokens: s.HttpTokens, + HttpPutResponseHopLimit: aws.Int32(s.HttpPutResponseHopLimit), } } - if s.InstanceMetadataTags == "enabled" { - runOpts.MetadataOptions.InstanceMetadataTags = aws.String(s.InstanceMetadataTags) + if s.InstanceMetadataTags == ec2types.InstanceMetadataTagsStateEnabled { + runOpts.MetadataOptions.InstanceMetadataTags = s.InstanceMetadataTags } // Collect tags for tagging on resource creation - var tagSpecs []*ec2.TagSpecification + var tagSpecs []ec2types.TagSpecification if len(ec2Tags) > 0 { - runTags := &ec2.TagSpecification{ - ResourceType: aws.String("instance"), + runTags := ec2types.TagSpecification{ + ResourceType: ec2types.ResourceTypeInstance, Tags: ec2Tags, } tagSpecs = append(tagSpecs, runTags) - networkInterfaceTags := &ec2.TagSpecification{ - ResourceType: aws.String("network-interface"), + networkInterfaceTags := ec2types.TagSpecification{ + ResourceType: ec2types.ResourceTypeNetworkInterface, Tags: ec2Tags, } @@ -196,8 +197,8 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } if len(volTags) > 0 { - runVolTags := &ec2.TagSpecification{ - ResourceType: aws.String("volume"), + runVolTags := ec2types.TagSpecification{ + ResourceType: ec2types.ResourceTypeVolume, Tags: volTags, } @@ -206,7 +207,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa // If our region supports it, set tag specifications if len(tagSpecs) > 0 && !s.IsRestricted { - runOpts.SetTagSpecifications(tagSpecs) + runOpts.TagSpecifications = tagSpecs ec2Tags.Report(ui) volTags.Report(ui) } @@ -221,9 +222,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa ui.Say(fmt.Sprintf("changing public IP address config to %t for instance on subnet %q", *s.AssociatePublicIpAddress.ToBoolPointer(), subnetId)) - runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ + runOpts.NetworkInterfaces = []ec2types.InstanceNetworkInterfaceSpecification{ { - DeviceIndex: aws.Int64(0), + DeviceIndex: aws.Int32(0), AssociatePublicIpAddress: s.AssociatePublicIpAddress.ToBoolPointer(), SubnetId: aws.String(subnetId), Groups: securityGroupIds, @@ -235,14 +236,14 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa runOpts.SecurityGroupIds = securityGroupIds } - if s.ExpectedRootDevice == "ebs" { - runOpts.InstanceInitiatedShutdownBehavior = &s.InstanceInitiatedShutdownBehavior + if s.ExpectedRootDevice == ec2types.DeviceTypeEbs { + runOpts.InstanceInitiatedShutdownBehavior = s.InstanceInitiatedShutdownBehavior } if len(s.LicenseSpecifications) > 0 { for i := range s.LicenseSpecifications { licenseConfigurationArn := s.LicenseSpecifications[i].LicenseConfigurationRequest.LicenseConfigurationArn - licenseSpecifications := []*ec2.LicenseConfigurationRequest{ + licenseSpecifications := []ec2types.LicenseConfigurationRequest{ { LicenseConfigurationArn: aws.String(licenseConfigurationArn), }, @@ -252,13 +253,13 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } if s.CapacityReservationPreference != "" { - runOpts.CapacityReservationSpecification = &ec2.CapacityReservationSpecification{ - CapacityReservationPreference: aws.String(s.CapacityReservationPreference), + runOpts.CapacityReservationSpecification = &ec2types.CapacityReservationSpecification{ + CapacityReservationPreference: s.CapacityReservationPreference, } } if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" { - runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2.CapacityReservationTarget{} + runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2types.CapacityReservationTarget{} if s.CapacityReservationId != "" { runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId = aws.String(s.CapacityReservationId) @@ -278,10 +279,10 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } if s.Tenancy != "" { - runOpts.Placement.Tenancy = aws.String(s.Tenancy) + runOpts.Placement.Tenancy = s.Tenancy } - var runResp *ec2.Reservation + var runResp *ec2.RunInstancesOutput err = retry.Config{ Tries: 11, ShouldRetry: func(err error) bool { @@ -289,7 +290,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - runResp, err = ec2conn.RunInstances(runOpts) + runResp, err = ec2conn.RunInstances(ctx, runOpts) return err }) @@ -306,7 +307,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa ui.Error(err.Error()) return multistep.ActionHalt } - instanceId = *runResp.Instances[0].InstanceId + instanceId = aws.ToString(runResp.Instances[0].InstanceId) // Set the instance ID so that the cleanup works properly s.instanceId = instanceId @@ -314,7 +315,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa return multistep.ActionHalt } describeInstance := &ec2.DescribeInstancesInput{ - InstanceIds: []*string{aws.String(instanceId)}, + InstanceIds: []string{instanceId}, } // there's a race condition that can happen because of AWS's eventual @@ -327,7 +328,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - r, err = ec2conn.DescribeInstances(describeInstance) + r, err = ec2conn.DescribeInstances(ctx, describeInstance) return err }) if err != nil || len(r.Reservations) == 0 || len(r.Reservations[0].Instances) == 0 { @@ -341,15 +342,15 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa if s.Debug { if instance.PublicDnsName != nil && *instance.PublicDnsName != "" { - ui.Message(fmt.Sprintf("Public DNS: %s", *instance.PublicDnsName)) + ui.Sayf("Public DNS: %s", *instance.PublicDnsName) } if instance.PublicIpAddress != nil && *instance.PublicIpAddress != "" { - ui.Message(fmt.Sprintf("Public IP: %s", *instance.PublicIpAddress)) + ui.Sayf("Public IP: %s", *instance.PublicIpAddress) } if instance.PrivateIpAddress != nil && *instance.PrivateIpAddress != "" { - ui.Message(fmt.Sprintf("Private IP: %s", *instance.PrivateIpAddress)) + ui.Sayf("Private IP: %s", *instance.PrivateIpAddress) } } @@ -373,9 +374,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { if len(ec2Tags) > 0 { - _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ + _, err := ec2conn.CreateTags(ctx, &ec2.CreateTagsInput{ Tags: ec2Tags, - Resources: []*string{instance.InstanceId}, + Resources: []string{aws.ToString(instance.InstanceId)}, }) return err } @@ -391,29 +392,30 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa if len(ec2Tags) > 0 { for _, networkInterface := range instance.NetworkInterfaces { - log.Printf("Tagging network interface %s", *networkInterface.NetworkInterfaceId) - _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ + niid := aws.ToString(networkInterface.NetworkInterfaceId) + log.Printf("Tagging network interface %s", niid) + _, err := ec2conn.CreateTags(ctx, &ec2.CreateTagsInput{ Tags: ec2Tags, - Resources: []*string{networkInterface.NetworkInterfaceId}, + Resources: []string{niid}, }) if err != nil { - ui.Error(fmt.Sprintf("Error tagging source instance's network interface %q: %s", *networkInterface.NetworkInterfaceId, err)) + ui.Error(fmt.Sprintf("Error tagging source instance's network interface %q: %s", niid, err)) } } } // Now tag volumes - volumeIds := make([]*string, 0) + volumeIds := make([]string, 0) for _, v := range instance.BlockDeviceMappings { if ebs := v.Ebs; ebs != nil { - volumeIds = append(volumeIds, ebs.VolumeId) + volumeIds = append(volumeIds, aws.ToString(ebs.VolumeId)) } } if len(volumeIds) > 0 && len(s.VolumeTags) > 0 { ui.Say("Adding tags to source EBS Volumes") - volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err) state.Put("error", err) @@ -422,7 +424,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } volumeTags.Report(ui) - _, err = ec2conn.CreateTags(&ec2.CreateTagsInput{ + _, err = ec2conn.CreateTags(ctx, &ec2.CreateTagsInput{ Resources: volumeIds, Tags: volumeTags, }) @@ -442,16 +444,16 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa func waitForInstanceReadiness( ctx context.Context, instanceId string, - ec2conn ec2iface.EC2API, + ec2conn clients.Ec2Client, ui packersdk.Ui, state multistep.StateBag, - waitUntilInstanceRunning func(context.Context, ec2iface.EC2API, string) error, + waitUntilInstanceRunning func(context.Context, clients.Ec2Client, string) error, ) error { - ui.Message(fmt.Sprintf("Instance ID: %s", instanceId)) + ui.Sayf("Instance ID: %s", instanceId) ui.Say(fmt.Sprintf("Waiting for instance (%v) to become ready...", instanceId)) describeInstance := &ec2.DescribeInstancesInput{ - InstanceIds: []*string{aws.String(instanceId)}, + InstanceIds: []string{instanceId}, } if err := waitUntilInstanceRunning(ctx, ec2conn, instanceId); err != nil { @@ -461,7 +463,7 @@ func waitForInstanceReadiness( // try to get some context from AWS on why was instance // transitioned to the unexpected state - if resp, e := ec2conn.DescribeInstances(describeInstance); e == nil { + if resp, e := ec2conn.DescribeInstances(ctx, describeInstance); e == nil { if len(resp.Reservations) > 0 && len(resp.Reservations[0].Instances) > 0 { instance := resp.Reservations[0].Instances[0] if instance.StateTransitionReason != nil && instance.StateReason != nil && instance.StateReason.Message != nil { @@ -477,18 +479,19 @@ func waitForInstanceReadiness( func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) + ctx := state.Get("context").(context.Context) // Terminate the source instance if it exists if s.instanceId != "" { ui.Say("Terminating the source AWS instance...") - if _, err := ec2conn.TerminateInstances(&ec2.TerminateInstancesInput{InstanceIds: []*string{&s.instanceId}}); err != nil { + if _, err := ec2conn.TerminateInstances(ctx, &ec2.TerminateInstancesInput{InstanceIds: []string{s.instanceId}}); err != nil { ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err)) return } - if err := s.PollingConfig.WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil { + if err := s.PollingConfig.WaitUntilInstanceTerminated(ctx, ec2conn, s.instanceId); err != nil { ui.Error(err.Error()) } } diff --git a/builder/common/step_run_spot_instance.go b/builder/common/step_run_spot_instance.go index 9ac83b06..4aff6ba8 100644 --- a/builder/common/step_run_spot_instance.go +++ b/builder/common/step_run_spot_instance.go @@ -13,10 +13,11 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -27,31 +28,31 @@ import ( ) type EC2BlockDeviceMappingsBuilder interface { - BuildEC2BlockDeviceMappings() []*ec2.BlockDeviceMapping + BuildEC2BlockDeviceMappings() []ec2types.BlockDeviceMapping } type StepRunSpotInstance struct { PollingConfig *AWSPollingConfig AssociatePublicIpAddress config.Trilean LaunchMappings EC2BlockDeviceMappingsBuilder - BlockDurationMinutes int64 + BlockDurationMinutes int32 Debug bool Comm *communicator.Config EbsOptimized bool - ExpectedRootDevice string + ExpectedRootDevice ec2types.DeviceType FleetTags map[string]string - HttpEndpoint string - HttpTokens string - HttpPutResponseHopLimit int64 - InstanceMetadataTags string + HttpEndpoint ec2types.LaunchTemplateInstanceMetadataEndpointState + HttpTokens ec2types.LaunchTemplateHttpTokensState + HttpPutResponseHopLimit int32 + InstanceMetadataTags ec2types.LaunchTemplateInstanceMetadataTagsState InstanceInitiatedShutdownBehavior string - InstanceType string + InstanceType ec2types.InstanceType Region string SourceAMI string - SpotAllocationStrategy string + SpotAllocationStrategy ec2types.SpotAllocationStrategy SpotPrice string SpotTags map[string]string - SpotInstanceTypes []string + SpotInstanceTypes []ec2types.InstanceType Tags map[string]string VolumeTags map[string]string UserData string @@ -68,8 +69,8 @@ type StepRunSpotInstance struct { // nearly identical except for the struct's name and one extra field in // EbsBlockDeviceResuest, which unfortunately means you can't just cast one // into the other. THANKS AMAZON. -func castBlockDeviceToRequest(bd *ec2.EbsBlockDevice) *ec2.LaunchTemplateEbsBlockDeviceRequest { - out := &ec2.LaunchTemplateEbsBlockDeviceRequest{ +func castBlockDeviceToRequest(bd *ec2types.EbsBlockDevice) *ec2types.LaunchTemplateEbsBlockDeviceRequest { + out := &ec2types.LaunchTemplateEbsBlockDeviceRequest{ DeleteOnTermination: bd.DeleteOnTermination, Encrypted: bd.Encrypted, Iops: bd.Iops, @@ -83,16 +84,16 @@ func castBlockDeviceToRequest(bd *ec2.EbsBlockDevice) *ec2.LaunchTemplateEbsBloc } func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string, - state multistep.StateBag, marketOptions *ec2.LaunchTemplateInstanceMarketOptionsRequest) *ec2.RequestLaunchTemplateData { + state multistep.StateBag, marketOptions *ec2types.LaunchTemplateInstanceMarketOptionsRequest) *ec2types.RequestLaunchTemplateData { blockDeviceMappings := s.LaunchMappings.BuildEC2BlockDeviceMappings() // Convert the BlockDeviceMapping into a // LaunchTemplateBlockDeviceMappingRequest. These structs are identical, // except for the EBS field -- on one, that field contains a // LaunchTemplateEbsBlockDeviceRequest, and on the other, it contains an // EbsBlockDevice. - var launchMappingRequests []*ec2.LaunchTemplateBlockDeviceMappingRequest + var launchMappingRequests []ec2types.LaunchTemplateBlockDeviceMappingRequest for _, mapping := range blockDeviceMappings { - launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{ + launchRequest := ec2types.LaunchTemplateBlockDeviceMappingRequest{ DeviceName: mapping.DeviceName, Ebs: castBlockDeviceToRequest(mapping.Ebs), VirtualName: mapping.VirtualName, @@ -110,7 +111,7 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string, log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings") DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz" for _, letter := range DefaultEphemeralDeviceLetters { - launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{ + launchRequest := ec2types.LaunchTemplateBlockDeviceMappingRequest{ DeviceName: aws.String("xvdc" + string(letter)), NoDevice: aws.String(""), } @@ -124,70 +125,70 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string, iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string)) // Create a launch template. - templateData := ec2.RequestLaunchTemplateData{ + templateData := ec2types.RequestLaunchTemplateData{ BlockDeviceMappings: launchMappingRequests, DisableApiTermination: aws.Bool(false), EbsOptimized: &s.EbsOptimized, - IamInstanceProfile: &ec2.LaunchTemplateIamInstanceProfileSpecificationRequest{Name: iamInstanceProfile}, + IamInstanceProfile: &ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{Name: iamInstanceProfile}, ImageId: &s.SourceAMI, InstanceMarketOptions: marketOptions, - Placement: &ec2.LaunchTemplatePlacementRequest{ + Placement: &ec2types.LaunchTemplatePlacementRequest{ AvailabilityZone: &az, }, UserData: userData, } // Create a network interface - securityGroupIds := aws.StringSlice(state.Get("securityGroupIds").([]string)) + securityGroupIds := state.Get("securityGroupIds").([]string) subnetId := state.Get("subnet_id").(string) if subnetId != "" { // Set up a full network interface - networkInterface := ec2.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{ + networkInterface := ec2types.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{ Groups: securityGroupIds, DeleteOnTermination: aws.Bool(true), - DeviceIndex: aws.Int64(0), + DeviceIndex: aws.Int32(0), SubnetId: aws.String(subnetId), } if s.AssociatePublicIpAddress != config.TriUnset { ui.Say(fmt.Sprintf("changing public IP address config to %t for instance on subnet %q", *s.AssociatePublicIpAddress.ToBoolPointer(), subnetId)) - networkInterface.SetAssociatePublicIpAddress(*s.AssociatePublicIpAddress.ToBoolPointer()) + networkInterface.AssociatePublicIpAddress = s.AssociatePublicIpAddress.ToBoolPointer() } - templateData.SetNetworkInterfaces([]*ec2.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{&networkInterface}) + templateData.NetworkInterfaces = []ec2types.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{networkInterface} } else { - templateData.SetSecurityGroupIds(securityGroupIds) + templateData.SecurityGroupIds = securityGroupIds } if s.IsBurstableInstanceType { - templateData.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsStandard)} + templateData.CreditSpecification = &ec2types.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsStandard)} } if s.EnableUnlimitedCredits { - templateData.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsUnlimited)} + templateData.CreditSpecification = &ec2types.CreditSpecificationRequest{CpuCredits: aws.String(CPUCreditsUnlimited)} } - if s.HttpEndpoint == "enabled" { - templateData.MetadataOptions = &ec2.LaunchTemplateInstanceMetadataOptionsRequest{ - HttpEndpoint: &s.HttpEndpoint, - HttpTokens: &s.HttpTokens, - HttpPutResponseHopLimit: &s.HttpPutResponseHopLimit, + if s.HttpEndpoint == ec2types.LaunchTemplateInstanceMetadataEndpointStateEnabled { + templateData.MetadataOptions = &ec2types.LaunchTemplateInstanceMetadataOptionsRequest{ + HttpEndpoint: s.HttpEndpoint, + HttpTokens: s.HttpTokens, + HttpPutResponseHopLimit: aws.Int32(s.HttpPutResponseHopLimit), } } - if s.InstanceMetadataTags == "enabled" { - templateData.MetadataOptions.InstanceMetadataTags = aws.String(s.InstanceMetadataTags) + if s.InstanceMetadataTags == ec2types.LaunchTemplateInstanceMetadataTagsStateEnabled { + templateData.MetadataOptions.InstanceMetadataTags = s.InstanceMetadataTags } // If instance type is not set, we'll just pick the lowest priced instance // available. if s.InstanceType != "" { - templateData.SetInstanceType(s.InstanceType) + templateData.InstanceType = s.InstanceType } if s.Comm.SSHKeyPairName != "" { - templateData.SetKeyName(s.Comm.SSHKeyPairName) + templateData.KeyName = aws.String(s.Comm.SSHKeyPairName) } return &templateData @@ -213,24 +214,24 @@ func (s *StepRunSpotInstance) LoadUserData() (string, error) { } func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(ec2iface.EC2API) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Launching a spot AWS instance...") // Get and validate the source AMI - image, ok := state.Get("source_image").(*ec2.Image) + image, ok := state.Get("source_image").(*ec2types.Image) if !ok { state.Put("error", fmt.Errorf("source_image type assertion failed")) return multistep.ActionHalt } s.SourceAMI = *image.ImageId - if s.ExpectedRootDevice != "" && *image.RootDeviceType != s.ExpectedRootDevice { + if s.ExpectedRootDevice != "" && image.RootDeviceType != s.ExpectedRootDevice { state.Put("error", fmt.Errorf( "The provided source AMI has an invalid root device type.\n"+ "Expected '%s', got '%s'.", - s.ExpectedRootDevice, *image.RootDeviceType)) + s.ExpectedRootDevice, image.RootDeviceType)) return multistep.ActionHalt } @@ -265,18 +266,18 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } volumeTags.Report(ui) - spotOptions := ec2.LaunchTemplateSpotMarketOptionsRequest{} + spotOptions := ec2types.LaunchTemplateSpotMarketOptionsRequest{} // The default is to set the maximum price to the OnDemand price. if s.SpotPrice != "auto" { - spotOptions.SetMaxPrice(s.SpotPrice) + spotOptions.MaxPrice = aws.String(s.SpotPrice) } if s.BlockDurationMinutes != 0 { - spotOptions.BlockDurationMinutes = &s.BlockDurationMinutes + spotOptions.BlockDurationMinutes = aws.Int32(s.BlockDurationMinutes) } - marketOptions := &ec2.LaunchTemplateInstanceMarketOptionsRequest{ + marketOptions := &ec2types.LaunchTemplateInstanceMarketOptionsRequest{ SpotOptions: &spotOptions, } - marketOptions.SetMarketType(ec2.MarketTypeSpot) + marketOptions.MarketType = ec2types.MarketTypeSpot spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, s.Region, state) if err != nil { @@ -287,7 +288,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } // Create a launch template for the instance - ui.Message("Loading User Data File...") + ui.Say("Loading User Data File...") // Generate a random name to avoid conflicting with other // instances of packer running in this AWS account @@ -301,7 +302,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) state.Put("error", err) return multistep.ActionHalt } - ui.Message("Creating Spot Fleet launch template...") + ui.Say("Creating Spot Fleet launch template...") templateData := s.CreateTemplateData(&userData, az, state, marketOptions) launchTemplate := &ec2.CreateLaunchTemplateInput{ LaunchTemplateData: templateData, @@ -311,8 +312,8 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) if len(spotTags) > 0 { launchTemplate.TagSpecifications = append( launchTemplate.TagSpecifications, - &ec2.TagSpecification{ - ResourceType: aws.String("launch-template"), + ec2types.TagSpecification{ + ResourceType: ec2types.ResourceTypeLaunchTemplate, Tags: spotTags, }, ) @@ -321,16 +322,16 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) if len(ec2Tags) > 0 { launchTemplate.LaunchTemplateData.TagSpecifications = append( launchTemplate.LaunchTemplateData.TagSpecifications, - &ec2.LaunchTemplateTagSpecificationRequest{ - ResourceType: aws.String("instance"), + ec2types.LaunchTemplateTagSpecificationRequest{ + ResourceType: ec2types.ResourceTypeInstance, Tags: ec2Tags, }, ) launchTemplate.LaunchTemplateData.TagSpecifications = append( launchTemplate.LaunchTemplateData.TagSpecifications, - &ec2.LaunchTemplateTagSpecificationRequest{ - ResourceType: aws.String("network-interface"), + ec2types.LaunchTemplateTagSpecificationRequest{ + ResourceType: ec2types.ResourceTypeNetworkInterface, Tags: ec2Tags, }, ) @@ -339,15 +340,15 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) if len(volumeTags) > 0 { launchTemplate.LaunchTemplateData.TagSpecifications = append( launchTemplate.LaunchTemplateData.TagSpecifications, - &ec2.LaunchTemplateTagSpecificationRequest{ - ResourceType: aws.String("volume"), + ec2types.LaunchTemplateTagSpecificationRequest{ + ResourceType: ec2types.ResourceTypeVolume, Tags: volumeTags, }, ) } // Tell EC2 to create the template - createLaunchTemplateOutput, err := ec2conn.CreateLaunchTemplate(launchTemplate) + createLaunchTemplateOutput, err := ec2conn.CreateLaunchTemplate(ctx, launchTemplate) if err != nil { err := fmt.Errorf("Error creating launch template for spot instance: %s", err) state.Put("error", err) @@ -356,21 +357,21 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } launchTemplateId := createLaunchTemplateOutput.LaunchTemplate.LaunchTemplateId - ui.Message(fmt.Sprintf("Created Spot Fleet launch template: %s", *launchTemplateId)) + ui.Sayf("Created Spot Fleet launch template: %s", *launchTemplateId) // Add overrides for each user-provided instance type - var overrides []*ec2.FleetLaunchTemplateOverridesRequest + var overrides []ec2types.FleetLaunchTemplateOverridesRequest for _, instanceType := range s.SpotInstanceTypes { - override := ec2.FleetLaunchTemplateOverridesRequest{ - InstanceType: aws.String(instanceType), + override := ec2types.FleetLaunchTemplateOverridesRequest{ + InstanceType: instanceType, } - overrides = append(overrides, &override) + overrides = append(overrides, override) } createFleetInput := &ec2.CreateFleetInput{ - LaunchTemplateConfigs: []*ec2.FleetLaunchTemplateConfigRequest{ + LaunchTemplateConfigs: []ec2types.FleetLaunchTemplateConfigRequest{ { - LaunchTemplateSpecification: &ec2.FleetLaunchTemplateSpecificationRequest{ + LaunchTemplateSpecification: &ec2types.FleetLaunchTemplateSpecificationRequest{ LaunchTemplateName: aws.String(launchTemplateName), Version: aws.String("1"), }, @@ -378,16 +379,16 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) }, }, ReplaceUnhealthyInstances: aws.Bool(false), - TargetCapacitySpecification: &ec2.TargetCapacitySpecificationRequest{ - TotalTargetCapacity: aws.Int64(1), - DefaultTargetCapacityType: aws.String("spot"), + TargetCapacitySpecification: &ec2types.TargetCapacitySpecificationRequest{ + TotalTargetCapacity: aws.Int32(1), + DefaultTargetCapacityType: ec2types.DefaultTargetCapacityTypeSpot, }, - Type: aws.String("instant"), + Type: ec2types.FleetTypeInstant, } if s.SpotAllocationStrategy != "" { - createFleetInput.SpotOptions = &ec2.SpotOptionsRequest{ - AllocationStrategy: aws.String(s.SpotAllocationStrategy), + createFleetInput.SpotOptions = &ec2types.SpotOptionsRequest{ + AllocationStrategy: s.SpotAllocationStrategy, } } @@ -403,8 +404,8 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) if len(fleetTags) > 0 { createFleetInput.TagSpecifications = append( createFleetInput.TagSpecifications, - &ec2.TagSpecification{ - ResourceType: aws.String("fleet"), + ec2types.TagSpecification{ + ResourceType: ec2types.ResourceTypeFleet, Tags: fleetTags, }, ) @@ -427,7 +428,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) }, RetryDelay: (&retry.Backoff{InitialBackoff: 500 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - createOutput, err = ec2conn.CreateFleet(createFleetInput) + createOutput, err = ec2conn.CreateFleet(ctx, createFleetInput) if err == nil && createOutput.Errors != nil { err = fmt.Errorf("errors: %v", createOutput.Errors) } @@ -459,7 +460,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) if len(createOutput.Errors) > 0 { errString := fmt.Sprintf("Error waiting for fleet request (%s) to become ready:", *createOutput.FleetId) for _, outErr := range createOutput.Errors { - errString = errString + aws.StringValue(outErr.ErrorMessage) + errString = errString + aws.ToString(outErr.ErrorMessage) } err = errors.New(errString) } @@ -468,7 +469,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) return multistep.ActionHalt } - instanceId = *createOutput.Instances[0].InstanceIds[0] + instanceId = createOutput.Instances[0].InstanceIds[0] // Set the instance ID so that the cleanup works properly s.instanceId = instanceId if err := waitForInstanceReadiness(ctx, instanceId, ec2conn, ui, state, s.PollingConfig.WaitUntilInstanceRunning); err != nil { @@ -481,8 +482,8 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) Tries: 11, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - describeOutput, err = ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{ - InstanceIds: []*string{aws.String(instanceId)}, + describeOutput, err = ec2conn.DescribeInstances(ctx, &ec2.DescribeInstancesInput{ + InstanceIds: []string{instanceId}, }) if len(describeOutput.Reservations) > 0 && len(describeOutput.Reservations[0].Instances) > 0 { if len(s.LaunchMappings.BuildEC2BlockDeviceMappings()) > 0 && len(describeOutput.Reservations[0].Instances[0].BlockDeviceMappings) == 0 { @@ -505,7 +506,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) spotTags.Report(ui) // Use the instance ID to find out the SIR, so that we can tag the spot // request associated with this instance. - sir := describeOutput.Reservations[0].Instances[0].SpotInstanceRequestId + sir := aws.ToString(describeOutput.Reservations[0].Instances[0].SpotInstanceRequestId) // Apply tags to the spot request. err = retry.Config{ @@ -513,9 +514,9 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) ShouldRetry: func(error) bool { return false }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ + _, err := ec2conn.CreateTags(ctx, &ec2.CreateTagsInput{ Tags: spotTags, - Resources: []*string{sir}, + Resources: []string{sir}, }) return err }) @@ -537,9 +538,9 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) return nil } - _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ + _, err := ec2conn.CreateTags(ctx, &ec2.CreateTagsInput{ Tags: ec2Tags, - Resources: []*string{instance.InstanceId}, + Resources: []string{aws.ToString(instance.InstanceId)}, }) return err }) @@ -551,16 +552,16 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) return multistep.ActionHalt } - volumeIds := make([]*string, 0) + volumeIds := make([]string, 0) for _, v := range instance.BlockDeviceMappings { if ebs := v.Ebs; ebs != nil { - volumeIds = append(volumeIds, ebs.VolumeId) + volumeIds = append(volumeIds, aws.ToString(ebs.VolumeId)) } } if len(volumeIds) > 0 && len(s.VolumeTags) > 0 { ui.Say("Adding tags to source EBS Volumes") - _, err = ec2conn.CreateTags(&ec2.CreateTagsInput{ + _, err = ec2conn.CreateTags(ctx, &ec2.CreateTagsInput{ Resources: volumeIds, Tags: volumeTags, }) @@ -597,19 +598,20 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } func (s *StepRunSpotInstance) Cleanup(state multistep.StateBag) { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) launchTemplateName := state.Get("launchTemplateName").(string) + ctx := state.Get("context").(context.Context) // Terminate the source instance if it exists if s.instanceId != "" { ui.Say("Terminating the source AWS instance...") - if _, err := ec2conn.TerminateInstances(&ec2.TerminateInstancesInput{InstanceIds: []*string{&s.instanceId}}); err != nil { + if _, err := ec2conn.TerminateInstances(ctx, &ec2.TerminateInstancesInput{InstanceIds: []string{s.instanceId}}); err != nil { ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err)) return } - if err := s.PollingConfig.WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil { + if err := s.PollingConfig.WaitUntilInstanceTerminated(ctx, ec2conn, s.instanceId); err != nil { ui.Error(err.Error()) } } @@ -618,7 +620,7 @@ func (s *StepRunSpotInstance) Cleanup(state multistep.StateBag) { deleteInput := &ec2.DeleteLaunchTemplateInput{ LaunchTemplateName: aws.String(launchTemplateName), } - if _, err := ec2conn.DeleteLaunchTemplate(deleteInput); err != nil { + if _, err := ec2conn.DeleteLaunchTemplate(ctx, deleteInput); err != nil { ui.Error(err.Error()) } } diff --git a/builder/common/step_run_spot_instance_test.go b/builder/common/step_run_spot_instance_test.go index c729e4e9..544b795c 100644 --- a/builder/common/step_run_spot_instance_test.go +++ b/builder/common/step_run_spot_instance_test.go @@ -9,10 +9,9 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -69,7 +68,7 @@ func TestCreateTemplateData(t *testing.T) { state := tStateSpot() stepRunSpotInstance := getBasicStep() template := stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state, - &ec2.LaunchTemplateInstanceMarketOptionsRequest{}) + &ec2types.LaunchTemplateInstanceMarketOptionsRequest{}) // expected := []*ec2.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{ // &ec2.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{ @@ -91,7 +90,7 @@ func TestCreateTemplateData(t *testing.T) { // Rerun, this time testing that we set security group IDs state.Put("subnet_id", "") template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state, - &ec2.LaunchTemplateInstanceMarketOptionsRequest{}) + &ec2types.LaunchTemplateInstanceMarketOptionsRequest{}) if template.NetworkInterfaces != nil { t.Fatalf("Template shouldn't contain network interfaces object if subnet_id is unset.") } @@ -99,7 +98,7 @@ func TestCreateTemplateData(t *testing.T) { // Rerun, this time testing that instance doesn't have instance profile is iamInstanceProfile is unset state.Put("iamInstanceProfile", "") template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state, - &ec2.LaunchTemplateInstanceMarketOptionsRequest{}) + &ec2types.LaunchTemplateInstanceMarketOptionsRequest{}) fmt.Println(template.IamInstanceProfile) if *template.IamInstanceProfile.Name != "" { t.Fatalf("Template shouldn't contain instance profile if iamInstanceProfile is unset.") @@ -111,7 +110,7 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { stepRunSpotInstance := getBasicStep() stepRunSpotInstance.NoEphemeral = true template := stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state, - &ec2.LaunchTemplateInstanceMarketOptionsRequest{}) + &ec2types.LaunchTemplateInstanceMarketOptionsRequest{}) if len(template.BlockDeviceMappings) != 26 { t.Fatalf("Should have created 26 mappings to keep ephemeral drives from appearing.") } @@ -146,55 +145,56 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { } type runSpotEC2ConnMock struct { - ec2iface.EC2API - CreateLaunchTemplateParams []*ec2.CreateLaunchTemplateInput - CreateLaunchTemplateFn func(*ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) + CreateLaunchTemplateFn func(context.Context, *ec2.CreateLaunchTemplateInput, ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) CreateFleetParams []*ec2.CreateFleetInput - CreateFleetFn func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) + CreateFleetFn func(context.Context, *ec2.CreateFleetInput, ...func(*ec2.Options)) (*ec2.CreateFleetOutput, error) CreateTagsParams []*ec2.CreateTagsInput - CreateTagsFn func(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) + CreateTagsFn func(context.Context, *ec2.CreateTagsInput, ...func(*ec2.Options)) (*ec2.CreateTagsOutput, error) DescribeInstancesParams []*ec2.DescribeInstancesInput - DescribeInstancesFn func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) + DescribeInstancesFn func(context.Context, *ec2.DescribeInstancesInput, ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) } -func (m *runSpotEC2ConnMock) CreateLaunchTemplate(req *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { +func (m *runSpotEC2ConnMock) CreateLaunchTemplate(ctx context.Context, req *ec2.CreateLaunchTemplateInput, opts ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) { m.CreateLaunchTemplateParams = append(m.CreateLaunchTemplateParams, req) - resp, err := m.CreateLaunchTemplateFn(req) + resp, err := m.CreateLaunchTemplateFn(ctx, req, opts...) return resp, err } -func (m *runSpotEC2ConnMock) CreateFleet(req *ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) { +func (m *runSpotEC2ConnMock) CreateFleet(ctx context.Context, req *ec2.CreateFleetInput, opts ...func(*ec2.Options)) (*ec2.CreateFleetOutput, error) { m.CreateFleetParams = append(m.CreateFleetParams, req) if m.CreateFleetFn != nil { - resp, err := m.CreateFleetFn(req) + resp, err := m.CreateFleetFn(ctx, req, opts...) return resp, err } else { return nil, nil } } -func (m *runSpotEC2ConnMock) DescribeInstances(req *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { +func (m *runSpotEC2ConnMock) DescribeInstances(ctx context.Context, req *ec2.DescribeInstancesInput, opts ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) { m.DescribeInstancesParams = append(m.DescribeInstancesParams, req) if m.DescribeInstancesFn != nil { - resp, err := m.DescribeInstancesFn(req) + resp, err := m.DescribeInstancesFn(ctx, req, opts...) return resp, err } else { return nil, nil } } +// we don't need this method to be mocked as in aws sdk v2, we use InstanceRunningWaiter +/* func (m *runSpotEC2ConnMock) WaitUntilInstanceRunningWithContext(ctx context.Context, _ *ec2.DescribeInstancesInput, opts ...request.WaiterOption) error { return nil } +*/ -func (m *runSpotEC2ConnMock) CreateTags(req *ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) { +func (m *runSpotEC2ConnMock) CreateTags(ctx context.Context, req *ec2.CreateTagsInput, opts ...func(*ec2.Options)) (*ec2.CreateTagsOutput, error) { m.CreateTagsParams = append(m.CreateTagsParams, req) if m.CreateTagsFn != nil { - resp, err := m.CreateTagsFn(req) + resp, err := m.CreateTagsFn(ctx, req, opts...) return resp, err } else { return nil, nil @@ -202,43 +202,43 @@ func (m *runSpotEC2ConnMock) CreateTags(req *ec2.CreateTagsInput) (*ec2.CreateTa } func defaultEc2Mock(instanceId, spotRequestId, volumeId, launchTemplateId *string) *runSpotEC2ConnMock { - instance := &ec2.Instance{ + instance := ec2types.Instance{ InstanceId: instanceId, SpotInstanceRequestId: spotRequestId, - BlockDeviceMappings: []*ec2.InstanceBlockDeviceMapping{ + BlockDeviceMappings: []ec2types.InstanceBlockDeviceMapping{ { - Ebs: &ec2.EbsInstanceBlockDevice{ + Ebs: &ec2types.EbsInstanceBlockDevice{ VolumeId: volumeId, }, }, }, } return &runSpotEC2ConnMock{ - CreateLaunchTemplateFn: func(in *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { + CreateLaunchTemplateFn: func(ctx context.Context, in *ec2.CreateLaunchTemplateInput, opts ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) { return &ec2.CreateLaunchTemplateOutput{ - LaunchTemplate: &ec2.LaunchTemplate{ + LaunchTemplate: &ec2types.LaunchTemplate{ LaunchTemplateId: launchTemplateId, }, Warning: nil, }, nil }, - CreateFleetFn: func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) { + CreateFleetFn: func(ctx context.Context, in *ec2.CreateFleetInput, opts ...func(*ec2.Options)) (*ec2.CreateFleetOutput, error) { return &ec2.CreateFleetOutput{ Errors: nil, FleetId: nil, - Instances: []*ec2.CreateFleetInstance{ + Instances: []ec2types.CreateFleetInstance{ { - InstanceIds: []*string{instanceId}, + InstanceIds: []string{*instanceId}, }, }, }, nil }, - DescribeInstancesFn: func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { + DescribeInstancesFn: func(ctx context.Context, in *ec2.DescribeInstancesInput, opts ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) { return &ec2.DescribeInstancesOutput{ NextToken: nil, - Reservations: []*ec2.Reservation{ + Reservations: []ec2types.Reservation{ { - Instances: []*ec2.Instance{instance}, + Instances: []ec2types.Instance{instance}, }, }, }, nil @@ -251,7 +251,7 @@ func TestRun(t *testing.T) { spotRequestId := aws.String("spot-id") volumeId := aws.String("volume-id") launchTemplateId := aws.String("launchTemplateId") - spotAllocationStrategy := aws.String("price-capacity-optimized") + spotAllocationStrategy := ec2types.SpotAllocationStrategyPriceCapacityOptimized ec2Mock := defaultEc2Mock(instanceId, spotRequestId, volumeId, launchTemplateId) uiMock := packersdk.TestUi(t) @@ -293,7 +293,7 @@ func TestRun(t *testing.T) { if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications) != 1 { t.Fatalf("exactly one launch template tag specification expected") } - if *ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].ResourceType != "launch-template" { + if ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].ResourceType != "launch-template" { t.Fatalf("resource type 'launch-template' expected") } if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags) != 1 { @@ -308,10 +308,10 @@ func TestRun(t *testing.T) { if len(ec2Mock.CreateFleetParams) != 1 { t.Fatalf("createFleet should be invoked once, but invoked %v", len(ec2Mock.CreateLaunchTemplateParams)) } - if *ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.DefaultTargetCapacityType != "spot" { + if ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.DefaultTargetCapacityType != "spot" { t.Fatalf("capacity type should be spot") } - if *ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.TotalTargetCapacity != 1 { + if aws.ToInt32(ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.TotalTargetCapacity) != 1 { t.Fatalf("target capacity should be 1") } if len(ec2Mock.CreateFleetParams[0].LaunchTemplateConfigs) != 1 { @@ -320,7 +320,7 @@ func TestRun(t *testing.T) { if *ec2Mock.CreateFleetParams[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification.LaunchTemplateName != *launchTemplateName { t.Fatalf("launchTemplateName should match in createLaunchTemplate and createFleet requests") } - if *ec2Mock.CreateFleetParams[0].SpotOptions.AllocationStrategy != *spotAllocationStrategy { + if ec2Mock.CreateFleetParams[0].SpotOptions.AllocationStrategy != spotAllocationStrategy { t.Fatalf("AllocationStrategy in CreateFleet request should match with spotAllocationStrategy param.") } @@ -332,7 +332,7 @@ func TestRun(t *testing.T) { if len(ec2Mock.DescribeInstancesParams) != 1 { t.Fatalf("describeInstancesParams should be invoked once, but invoked %v", len(ec2Mock.DescribeInstancesParams)) } - if *ec2Mock.DescribeInstancesParams[0].InstanceIds[0] != *instanceId { + if ec2Mock.DescribeInstancesParams[0].InstanceIds[0] != *instanceId { t.Fatalf("instanceId should match from createFleet response") } @@ -340,13 +340,13 @@ func TestRun(t *testing.T) { if len(ec2Mock.CreateTagsParams) != 3 { t.Fatalf("createTags should be invoked 3 times") } - if len(ec2Mock.CreateTagsParams[0].Resources) != 1 || *ec2Mock.CreateTagsParams[0].Resources[0] != *spotRequestId { + if len(ec2Mock.CreateTagsParams[0].Resources) != 1 || ec2Mock.CreateTagsParams[0].Resources[0] != *spotRequestId { t.Fatalf("should create tags for spot request") } - if len(ec2Mock.CreateTagsParams[1].Resources) != 1 || *ec2Mock.CreateTagsParams[1].Resources[0] != *instanceId { + if len(ec2Mock.CreateTagsParams[1].Resources) != 1 || ec2Mock.CreateTagsParams[1].Resources[0] != *instanceId { t.Fatalf("should create tags for instance") } - if len(ec2Mock.CreateTagsParams[2].Resources) != 1 || ec2Mock.CreateTagsParams[2].Resources[0] != volumeId { + if len(ec2Mock.CreateTagsParams[2].Resources) != 1 || ec2Mock.CreateTagsParams[2].Resources[0] != *volumeId { t.Fatalf("should create tags for volume") } } diff --git a/builder/common/step_source_ami_info.go b/builder/common/step_source_ami_info.go index b5600e5e..aa09ec58 100644 --- a/builder/common/step_source_ami_info.go +++ b/builder/common/step_source_ami_info.go @@ -9,7 +9,10 @@ import ( "sort" "time" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -25,12 +28,12 @@ type StepSourceAMIInfo struct { SourceAmi string EnableAMISriovNetSupport bool EnableAMIENASupport config.Trilean - AMIVirtType string + AMIVirtType ec2types.VirtualizationType AmiFilters AmiFilterOptions IncludeDeprecated bool } -type imageSort []*ec2.Image +type imageSort []ec2types.Image func (a imageSort) Len() int { return len(a) } func (a imageSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } @@ -41,14 +44,14 @@ func (a imageSort) Less(i, j int) bool { } // Returns the most recent AMI out of a slice of images. -func mostRecentAmi(images []*ec2.Image) *ec2.Image { +func mostRecentAmi(images []ec2types.Image) ec2types.Image { sortedImages := images sort.Sort(imageSort(sortedImages)) return sortedImages[len(sortedImages)-1] } func (s *StepSourceAMIInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) params := &ec2.DescribeImagesInput{ @@ -56,17 +59,17 @@ func (s *StepSourceAMIInfo) Run(ctx context.Context, state multistep.StateBag) m } if s.SourceAmi != "" { - params.ImageIds = []*string{&s.SourceAmi} + params.ImageIds = []string{s.SourceAmi} } - image, err := s.AmiFilters.GetFilteredImage(params, ec2conn) + image, err := s.AmiFilters.GetFilteredImage(ctx, params, ec2conn) if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } - ui.Message(fmt.Sprintf("Found Image ID: %s", *image.ImageId)) + ui.Say(fmt.Sprintf("Found Image ID: %s", aws.ToString(image.ImageId))) // Enhanced Networking can only be enabled on HVM AMIs. // See http://goo.gl/icuXh5 @@ -85,14 +88,14 @@ func (s *StepSourceAMIInfo) Run(ctx context.Context, state multistep.StateBag) m func (s *StepSourceAMIInfo) Cleanup(multistep.StateBag) {} -func (s *StepSourceAMIInfo) canEnableEnhancedNetworking(image *ec2.Image) error { - if s.AMIVirtType == "hvm" { +func (s *StepSourceAMIInfo) canEnableEnhancedNetworking(image *ec2types.Image) error { + if s.AMIVirtType == ec2types.VirtualizationTypeHvm { return nil } if s.AMIVirtType != "" { return fmt.Errorf("Cannot enable enhanced networking, AMIVirtType '%s' is not HVM", s.AMIVirtType) } - if *image.VirtualizationType != "hvm" { + if image.VirtualizationType != ec2types.VirtualizationTypeHvm { return fmt.Errorf("Cannot enable enhanced networking, source AMI '%s' is not HVM", s.SourceAmi) } return nil diff --git a/builder/common/tags.go b/builder/common/tags.go index c87f4469..0427080c 100644 --- a/builder/common/tags.go +++ b/builder/common/tags.go @@ -6,9 +6,9 @@ package common import ( "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata" @@ -16,17 +16,17 @@ import ( ) type TagMap map[string]string -type EC2Tags []*ec2.Tag +type EC2Tags []ec2types.Tag func (t EC2Tags) Report(ui packersdk.Ui) { for _, tag := range t { - ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"", - aws.StringValue(tag.Key), aws.StringValue(tag.Value))) + ui.Say(fmt.Sprintf("Adding tag: \"%s\": \"%s\"", + aws.ToString(tag.Key), aws.ToString(tag.Value))) } } func (t TagMap) EC2Tags(ictx interpolate.Context, region string, state multistep.StateBag) (EC2Tags, error) { - var ec2Tags []*ec2.Tag + var ec2Tags EC2Tags generatedData := packerbuilderdata.GeneratedData{State: state} ictx.Data = extractBuildInfo(region, state, &generatedData) @@ -39,7 +39,7 @@ func (t TagMap) EC2Tags(ictx interpolate.Context, region string, state multistep if err != nil { return nil, fmt.Errorf("Error processing tag: %s:%s - %s", key, value, err) } - ec2Tags = append(ec2Tags, &ec2.Tag{ + ec2Tags = append(ec2Tags, ec2types.Tag{ Key: aws.String(interpolatedKey), Value: aws.String(interpolatedValue), }) @@ -47,8 +47,8 @@ func (t TagMap) EC2Tags(ictx interpolate.Context, region string, state multistep return ec2Tags, nil } -func (t TagMap) IamTags(ictx interpolate.Context, region string, state multistep.StateBag) ([]*iam.Tag, error) { - var iamTags []*iam.Tag +func (t TagMap) IamTags(ictx interpolate.Context, region string, state multistep.StateBag) ([]iamtypes.Tag, error) { + var iamTags []iamtypes.Tag generatedData := packerbuilderdata.GeneratedData{State: state} ictx.Data = extractBuildInfo(region, state, &generatedData) @@ -61,7 +61,7 @@ func (t TagMap) IamTags(ictx interpolate.Context, region string, state multistep if err != nil { return nil, fmt.Errorf("Error processing tag: %s:%s - %s", key, value, err) } - iamTags = append(iamTags, &iam.Tag{ + iamTags = append(iamTags, iamtypes.Tag{ Key: aws.String(interpolatedKey), Value: aws.String(interpolatedValue), }) @@ -69,12 +69,12 @@ func (t TagMap) IamTags(ictx interpolate.Context, region string, state multistep return iamTags, nil } -func (t EC2Tags) TagSpecifications(resourceType ...string) []*ec2.TagSpecification { - var tagSpecs []*ec2.TagSpecification +func (t EC2Tags) TagSpecifications(resourceType ...string) []*ec2types.TagSpecification { + var tagSpecs []*ec2types.TagSpecification if len(t) > 0 { for _, resource := range resourceType { - runTags := &ec2.TagSpecification{ - ResourceType: aws.String(resource), + runTags := &ec2types.TagSpecification{ + ResourceType: ec2types.ResourceType(resource), Tags: t, } tagSpecs = append(tagSpecs, runTags) diff --git a/builder/common/test_helper_funcs.go b/builder/common/test_helper_funcs.go index 4976ea4b..bb57bdd5 100644 --- a/builder/common/test_helper_funcs.go +++ b/builder/common/test_helper_funcs.go @@ -4,25 +4,23 @@ package common import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/hashicorp/packer-plugin-amazon/common/clients" ) type mockEC2Client struct { - ec2iface.EC2API + clients.Ec2Client } func FakeAccessConfig() *AccessConfig { accessConfig := AccessConfig{ - getEC2Connection: func() ec2iface.EC2API { + getEC2Connection: func() clients.Ec2Client { return &mockEC2Client{} }, PollingConfig: new(AWSPollingConfig), } - accessConfig.session = session.Must(session.NewSession(&aws.Config{ - Region: aws.String("us-west-1"), - })) - + accessConfig.awsConfig = &aws.Config{ + Region: "us-east-1", + } return &accessConfig } diff --git a/builder/ebs/step_enable_fast_launch.go b/builder/ebs/step_enable_fast_launch.go index 628836fa..646d00f4 100644 --- a/builder/ebs/step_enable_fast_launch.go +++ b/builder/ebs/step_enable_fast_launch.go @@ -84,7 +84,7 @@ func (s *stepEnableFastLaunch) Run(ctx context.Context, state multistep.StateBag } // Casting is somewhat unsafe, but since the retryer below only - // accepts this type, and not ec2iface.EC2API, we can safely + // accepts this type, and not clients.Ec2Client, we can safely // do this here, unless the `GetRegionConn` function evolves // later, in which case this will fail. // todo check this diff --git a/builder/instance/builder.go b/builder/instance/builder.go index b8461791..0ad6a79e 100644 --- a/builder/instance/builder.go +++ b/builder/instance/builder.go @@ -15,8 +15,9 @@ import ( "os" "strings" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/hashicorp/hcl/v2/hcldec" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" "github.com/hashicorp/packer-plugin-sdk/common" @@ -94,7 +95,7 @@ type Config struct { // NitroTPM Support. Valid options are `v2.0`. See the documentation on // [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for // more information. Only enabled if a valid option is provided, otherwise ignored. - TpmSupport string `mapstructure:"tpm_support" required:"false"` + TpmSupport ec2types.TpmSupportValues `mapstructure:"tpm_support" required:"false"` ctx interpolate.Context } @@ -240,8 +241,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { "Packer, inclusion of enable_t2_unlimited will error your builds.") } - if b.config.TpmSupport != "" && b.config.TpmSupport != ec2.TpmSupportValuesV20 { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`The only valid tpm_support value is %q`, ec2.TpmSupportValuesV20)) + if b.config.TpmSupport != "" && b.config.TpmSupport != ec2types.TpmSupportValuesV20 { + errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`The only valid tpm_support value is %q`, ec2types.TpmSupportValuesV20)) } if errs != nil && len(errs.Errors) > 0 { @@ -254,12 +255,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { } func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - session, err := b.config.Session() + awscfg, err := b.config.GetAWSConfig(ctx) if err != nil { return nil, err } - ec2conn := ec2.New(session) - iam := iam.New(session) + ec2conn := ec2.NewFromConfig(awscfg.Copy()) + iam := iam.NewFromConfig(awscfg.Copy()) // Setup the state bag and initial state for the steps state := new(multistep.BasicStateBag) @@ -268,10 +269,10 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) state.Put("ami_config", &b.config.AMIConfig) state.Put("ec2", ec2conn) state.Put("iam", iam) - state.Put("awsSession", session) + state.Put("awsConfig", awscfg) state.Put("hook", hook) state.Put("ui", ui) - state.Put("region", ec2conn.Config.Region) + state.Put("region", awscfg.Region) generatedData := &packerbuilderdata.GeneratedData{State: state} var instanceStep multistep.Step @@ -290,7 +291,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) EnableUnlimitedCredits: b.config.EnableUnlimitedCredits, InstanceType: b.config.InstanceType, FleetTags: b.config.FleetTags, - Region: *ec2conn.Config.Region, + Region: awscfg.Region, SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotInstanceTypes: b.config.SpotInstanceTypes, @@ -301,8 +302,8 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) UserDataFile: b.config.UserDataFile, } } else { - var tenancy string - tenancies := []string{b.config.Placement.Tenancy, b.config.Tenancy} + var tenancy ec2types.Tenancy + tenancies := []ec2types.Tenancy{b.config.Placement.Tenancy, b.config.Tenancy} for i := range tenancies { if tenancies[i] != "" { @@ -399,8 +400,8 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) BuildName: b.config.PackerBuildName, }, &awscommon.StepCreateSSMTunnel{ - AWSSession: session, - Region: *ec2conn.Config.Region, + AwsConfig: awscfg.Copy(), + Region: awscfg.Region, PauseBeforeSSM: b.config.PauseBeforeSSM, LocalPortNumber: b.config.SessionManagerPort, RemotePortNumber: b.config.Comm.Port(), @@ -412,6 +413,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) // the communicator will ultimately determine which port to use. Config: &b.config.RunConfig.Comm, Host: awscommon.SSHHost( + ctx, ec2conn, b.config.SSHInterface, b.config.Comm.Host(), @@ -457,7 +459,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) RegionKeyIds: b.config.AMIRegionKMSKeyIDs, EncryptBootVolume: b.config.AMIEncryptBootVolume, Name: b.config.AMIName, - OriginalRegion: *ec2conn.Config.Region, + OriginalRegion: awscfg.Region, AMISnapshotCopyDurationMinutes: b.config.AMISnapshotCopyDurationMinutes, }, &awscommon.StepEnableDeprecation{ @@ -506,7 +508,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) artifact := &awscommon.Artifact{ Amis: state.Get("amis").(map[string]string), BuilderIdValue: BuilderId, - Session: session, + Config: awscfg, StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, } diff --git a/builder/instance/step_register_ami.go b/builder/instance/step_register_ami.go index 0aac3bb4..bce7b92e 100644 --- a/builder/instance/step_register_ami.go +++ b/builder/instance/step_register_ami.go @@ -7,9 +7,11 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/random" @@ -21,12 +23,13 @@ type StepRegisterAMI struct { EnableAMIENASupport config.Trilean EnableAMISriovNetSupport bool AMISkipBuildRegion bool - TpmSupport string + TpmSupport ec2types.TpmSupportValues } func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) - ec2conn := state.Get("ec2").(*ec2.EC2) + awscfg := state.Get("awsConfig").(*aws.Config) + ec2conn := state.Get("ec2").(clients.Ec2Client) manifestPath := state.Get("remote_manifest_path").(string) ui := state.Get("ui").(packersdk.Ui) @@ -56,7 +59,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul } if config.AMIVirtType != "" { - registerOpts.VirtualizationType = aws.String(config.AMIVirtType) + registerOpts.VirtualizationType = aws.String(string(config.AMIVirtType)) } if s.EnableAMISriovNetSupport { @@ -70,10 +73,10 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul registerOpts.EnaSupport = aws.Bool(true) } if s.TpmSupport != "" { - registerOpts.TpmSupport = aws.String(s.TpmSupport) + registerOpts.TpmSupport = s.TpmSupport } - registerResp, err := ec2conn.RegisterImage(registerOpts) + registerResp, err := ec2conn.RegisterImage(ctx, registerOpts) if err != nil { state.Put("error", fmt.Errorf("Error registering AMI: %s", err)) ui.Error(state.Get("error").(error).Error()) @@ -83,7 +86,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul // Set the AMI ID in the state ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageId)) amis := make(map[string]string) - amis[*ec2conn.Config.Region] = *registerResp.ImageId + amis[awscfg.Region] = *registerResp.ImageId state.Put("amis", amis) // Wait for the image to become ready diff --git a/builder/instance/step_upload_bundle.go b/builder/instance/step_upload_bundle.go index 231362bb..1dfc26bb 100644 --- a/builder/instance/step_upload_bundle.go +++ b/builder/instance/step_upload_bundle.go @@ -35,12 +35,11 @@ func (s *StepUploadBundle) Run(ctx context.Context, state multistep.StateBag) mu accessKey := config.AccessKey secretKey := config.SecretKey - session, err := config.AccessConfig.Session() - region := *session.Config.Region - accessConfig := session.Config + awscfg, err := config.AccessConfig.GetAWSConfig(ctx) + region := awscfg.Region var token string if err == nil && accessKey == "" && secretKey == "" { - credentials, err := accessConfig.Credentials.Get() + credentials, err := awscfg.Credentials.Retrieve(ctx) if err == nil { accessKey = credentials.AccessKeyID secretKey = credentials.SecretAccessKey diff --git a/common/clients/ec2_client.go b/common/clients/ec2_client.go index 22706c1f..4a26fc2f 100644 --- a/common/clients/ec2_client.go +++ b/common/clients/ec2_client.go @@ -14,6 +14,7 @@ type Ec2Client interface { ec2.DescribeInstancesAPIClient ec2.DescribeSnapshotsAPIClient ec2.DescribeImportImageTasksAPIClient + ec2.DescribeSpotInstanceRequestsAPIClient AuthorizeSecurityGroupIngress(ctx context.Context, params *ec2.AuthorizeSecurityGroupIngressInput, optFns ...func(*ec2.Options)) (*ec2.AuthorizeSecurityGroupIngressOutput, error) AttachVolume(ctx context.Context, params *ec2.AttachVolumeInput, optFns ...func(*ec2.Options)) (*ec2.AttachVolumeOutput, error) @@ -26,6 +27,7 @@ type Ec2Client interface { CreateTags(ctx context.Context, params *ec2.CreateTagsInput, optFns ...func(*ec2.Options)) (*ec2.CreateTagsOutput, error) CreateSnapshot(ctx context.Context, params *ec2.CreateSnapshotInput, optFns ...func(*ec2.Options)) (*ec2.CreateSnapshotOutput, error) CreateSecurityGroup(ctx context.Context, params *ec2.CreateSecurityGroupInput, optFns ...func(*ec2.Options)) (*ec2.CreateSecurityGroupOutput, error) + CreateVolume(ctx context.Context, params *ec2.CreateVolumeInput, optFns ...func(*ec2.Options)) (*ec2.CreateVolumeOutput, error) DetachVolume(ctx context.Context, params *ec2.DetachVolumeInput, optFns ...func(*ec2.Options)) (*ec2.DetachVolumeOutput, error) DescribeInstances(ctx context.Context, params *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) diff --git a/common/step_run_spot_instance_test.go b/common/step_run_spot_instance_test.go index 3b9bd5d3..fb9d198b 100644 --- a/common/step_run_spot_instance_test.go +++ b/common/step_run_spot_instance_test.go @@ -148,7 +148,7 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { } type runSpotEC2ConnMock struct { - //ec2iface.EC2API + //clients.Ec2Client clients.Ec2Client CreateLaunchTemplateParams []*ec2.CreateLaunchTemplateInput diff --git a/go.mod b/go.mod index a8434e59..58899521 100644 --- a/go.mod +++ b/go.mod @@ -1,163 +1,181 @@ module github.com/hashicorp/packer-plugin-amazon -go 1.25.10 +go 1.26.0 + +toolchain go1.26.2 require ( - github.com/aws/aws-sdk-go v1.55.6 - github.com/aws/aws-sdk-go-v2/credentials v1.18.3 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.85 - github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.29.1 - github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 - github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.37.0 - github.com/aws/aws-sdk-go-v2/service/ssm v1.61.1 - github.com/aws/aws-sdk-go-v2/service/sts v1.36.0 + github.com/aws/aws-sdk-go v1.55.8 + github.com/aws/aws-sdk-go-v2/credentials v1.19.16 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.18 + github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.32.22 + github.com/aws/aws-sdk-go-v2/service/iam v1.53.10 + github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.7 + github.com/aws/aws-sdk-go-v2/service/ssm v1.68.6 + github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 github.com/google/go-cmp v0.7.0 - github.com/hashicorp/aws-sdk-go-base v0.7.1 - github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65 + github.com/hashicorp/aws-sdk-go-base v1.1.0 + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/hcl/v2 v2.24.0 - github.com/hashicorp/packer-plugin-sdk v0.6.8 - github.com/hashicorp/vault/api v1.16.0 + github.com/hashicorp/packer-plugin-sdk v0.6.7 + github.com/hashicorp/vault/api v1.23.0 github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.11.1 - github.com/zclconf/go-cty v1.16.3 - golang.org/x/sys v0.39.0 + github.com/zclconf/go-cty v1.18.1 + golang.org/x/sys v0.44.0 ) require ( - cloud.google.com/go v0.112.2 // indirect - cloud.google.com/go/auth v0.16.0 // indirect + cel.dev/expr v0.25.2 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.20.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect - cloud.google.com/go/iam v1.1.6 // indirect - cloud.google.com/go/storage v1.39.1 // indirect + cloud.google.com/go/iam v1.11.0 // indirect + cloud.google.com/go/monitoring v1.29.0 // indirect + cloud.google.com/go/storage v1.62.1 // indirect github.com/Azure/go-ntlmssp v0.1.1 // indirect github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect - github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect - github.com/aws/aws-sdk-go-v2/service/sns v1.34.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sqs v1.38.6 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.27.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.32.0 // indirect + github.com/armon/go-metrics v0.5.4 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 // indirect + github.com/aws/aws-sdk-go-v2/service/sns v1.39.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sqs v1.42.27 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 // indirect github.com/bodgit/ntlmssp v0.0.0-20240506230425-31973bb52d9b // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + github.com/hashicorp/go-metrics v0.5.4 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.10.0 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect github.com/jcmturner/goidentity/v6 v6.0.1 // indirect github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.61.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect - golang.org/x/mod v0.30.0 // indirect - golang.org/x/tools v0.39.0 // indirect + golang.org/x/mod v0.36.0 // indirect + golang.org/x/tools v0.45.0 // indirect ) require ( - github.com/aws/aws-sdk-go-v2 v1.37.2 - github.com/aws/aws-sdk-go-v2/config v1.30.3 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.218.0 - github.com/aws/smithy-go v1.22.5 + github.com/aws/aws-sdk-go-v2 v1.41.7 + github.com/aws/aws-sdk-go-v2/config v1.32.17 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.301.0 + github.com/aws/smithy-go v1.25.1 github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dylanmei/iso8601 v0.1.0 // indirect - github.com/fatih/color v1.18.0 // indirect + github.com/fatih/color v1.19.0 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect - github.com/gofrs/flock v0.8.1 // indirect + github.com/gofrs/flock v0.13.0 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect - github.com/hashicorp/consul/api v1.25.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.15 // indirect + github.com/googleapis/gax-go/v2 v2.22.0 // indirect + github.com/hashicorp/consul/api v1.34.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-getter/gcs/v2 v2.2.2 // indirect - github.com/hashicorp/go-getter/s3/v2 v2.2.2 // indirect - github.com/hashicorp/go-getter/v2 v2.2.2 // indirect + github.com/hashicorp/go-getter/gcs/v2 v2.2.3 // indirect + github.com/hashicorp/go-getter/s3/v2 v2.2.3 // indirect + github.com/hashicorp/go-getter/v2 v2.2.3 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.7 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/serf v0.10.1 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hashicorp/go-version v1.9.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/hcl v1.0.1-vault-7 // indirect + github.com/hashicorp/serf v0.10.2 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.11.2 // indirect + github.com/klauspost/compress v1.18.6 // indirect github.com/kr/fs v0.1.0 // indirect github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect - github.com/masterzen/winrm v0.0.0-20250927112105-5f8e6c707321 // indirect + github.com/masterzen/winrm v0.0.0-20260407182533-5570be7f80cf // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/iochan v1.0.0 // indirect - github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect - github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db // indirect - github.com/pkg/sftp v1.13.2 // indirect + github.com/packer-community/winrmcp v0.0.0-20221126162354-6e900dd2c68f // indirect + github.com/pkg/sftp v1.13.10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect - github.com/ugorji/go/codec v1.2.6 // indirect + github.com/ugorji/go/codec v1.3.1 // indirect github.com/ulikunitz/xz v0.5.15 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/net v0.48.0 // indirect - golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect - golang.org/x/time v0.11.0 // indirect - google.golang.org/api v0.230.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/grpc v1.79.3 // indirect - google.golang.org/protobuf v1.36.10 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect + golang.org/x/net v0.54.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect + golang.org/x/time v0.15.0 // indirect + google.golang.org/api v0.278.0 // indirect + google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 // indirect + google.golang.org/grpc v1.81.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/zclconf/go-cty => github.com/nywilken/go-cty v1.13.3 // added by packer-sdc fix as noted in github.com/hashicorp/packer-plugin-sdk/issues/187 +replace ( + github.com/armon/go-metrics => github.com/hashicorp/go-metrics v0.5.1 + github.com/zclconf/go-cty => github.com/nywilken/go-cty v1.13.3 // added by packer-sdc fix as noted in github.com/hashicorp/packer-plugin-sdk/issues/187 +) diff --git a/go.sum b/go.sum index c824c319..9322faa1 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,39 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.112.2 h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw= -cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= -cloud.google.com/go/auth v0.16.0 h1:Pd8P1s9WkcrBE2n/PhAwKsdrR35V3Sg2II9B+ndM3CU= -cloud.google.com/go/auth v0.16.0/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI= +cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= -cloud.google.com/go/storage v1.39.1 h1:MvraqHKhogCOTXTlct/9C3K3+Uy2jBmFYb3/Sp6dVtY= -cloud.google.com/go/storage v1.39.1/go.mod h1:xK6xZmxZmo+fyP7+DEF6FhNc24/JAe95OLyOHCXFH1o= +cloud.google.com/go/iam v1.11.0 h1:KieQ9Pb+LLPak1O3Rv3GgCxhnmkYf7Xyh0P5HfF1jFM= +cloud.google.com/go/iam v1.11.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= +cloud.google.com/go/logging v1.17.0 h1:rUFekZYwHiKElXCyz3zYBGz4BOeIqzgCKxVLdgrZ5mY= +cloud.google.com/go/logging v1.17.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= +cloud.google.com/go/longrunning v0.12.0 h1:wLv2hXvID9zHejLtcPo1B0JBjErnwZCYAPKSTa65xpY= +cloud.google.com/go/longrunning v0.12.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= +cloud.google.com/go/monitoring v1.29.0 h1:AHhDsFaSax1/4k+qlIDX/SDGe6hggnfXJ9dkgD9qBPY= +cloud.google.com/go/monitoring v1.29.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= +cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= +cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cloud.google.com/go/trace v1.15.0 h1:kAYkTwKyYHkGtAGFuu6qaUFRBkOVr+d1Yo44yZtGtgg= +cloud.google.com/go/trace v1.15.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw= github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 h1:w0E0fgc1YafGEh5cROhlROMWXiNoZqApk2PDN0M1+Ns= github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0 h1:ZIT85vKP7LBS84XJ0WdJ3dPOX3iz4j3c0+lpajGQMyo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0/go.mod h1:rqP9UEhOXv9WhQ7Gjz+G5y/pf8+BJZW5/Ts0AhE0PwE= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 h1:0YP0+/ixwu+Uqeu/FGiBZNQ19huiUxxiPXIc9WsLKuQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= @@ -25,6 +42,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antchfx/xmlquery v1.3.5 h1:I7TuBRqsnfFuL11ruavGm911Awx9IqSdiU6W/ztSmVw= github.com/antchfx/xmlquery v1.3.5/go.mod h1:64w0Xesg2sTaawIdNqMB+7qaW/bSqkQm+ssPaCMWNnc= github.com/antchfx/xpath v1.1.11 h1:WOFtK8TVAjLm3lbgqeP0arlHpvCEeTANeWZ/csPpJkQ= @@ -33,93 +51,85 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6 github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= -github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.37.2 h1:xkW1iMYawzcmYFYEV0UCMxc8gSsjCGEhBXQkdQywVbo= -github.com/aws/aws-sdk-go-v2 v1.37.2/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= -github.com/aws/aws-sdk-go-v2/config v1.30.3 h1:utupeVnE3bmB221W08P0Moz1lDI3OwYa2fBtUhl7TCc= -github.com/aws/aws-sdk-go-v2/config v1.30.3/go.mod h1:NDGwOEBdpyZwLPlQkpKIO7frf18BW8PaCmAM9iUxQmI= -github.com/aws/aws-sdk-go-v2/credentials v1.18.3 h1:ptfyXmv+ooxzFwyuBth0yqABcjVIkjDL0iTYZBSbum8= -github.com/aws/aws-sdk-go-v2/credentials v1.18.3/go.mod h1:Q43Nci++Wohb0qUh4m54sNln0dbxJw8PvQWkrwOkGOI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2 h1:nRniHAvjFJGUCl04F3WaAj7qp/rcz5Gi1OVoj5ErBkc= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2/go.mod h1:eJDFKAMHHUvv4a0Zfa7bQb//wFNUXGrbFpYRCHe2kD0= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.85 h1:AfpstoiaenxGSCUheWiicgZE5XXS5Fi4CcQ4PA/x+Qw= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.85/go.mod h1:HxiF0Fd6WHWjdjOffLkCauq7JqzWqMMq0iUVLS7cPQc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2 h1:sPiRHLVUIIQcoVZTNwqQcdtjkqkPopyYmIX0M5ElRf4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2/go.mod h1:ik86P3sgV+Bk7c1tBFCwI3VxMoSEwl4YkRB9xn1s340= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.2 h1:ZdzDAg075H6stMZtbD2o+PyB933M/f20e9WmCBC17wA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.2/go.mod h1:eE1IIzXG9sdZCB0pNNpMpsYTLl4YdOQD3njiVN1e/E4= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37/go.mod h1:Pi6ksbniAWVwu2S8pEzcYPyhUkAcLaufxN7PfAUQjBk= -github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.2 h1:bjp0bB5k3MQ9diYqjV1/ocHZHdTnoKSqQRa2s5B+648= -github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.2/go.mod h1:yYaWRnVSPyAmexW5t7G3TcuYoalYfT+xQwzWsvtUQ7M= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.218.0 h1:QPYsTfcPpPhkF+37pxLcl3xbQz2SRxsShQNB6VCkvLo= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.218.0/go.mod h1:ouvGEfHbLaIlWwpDpOVWPWR+YwO0HDv3vm5tYLq8ImY= -github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.29.1 h1:2mIT1nT5kjOE7jBdE/uK6XX08NbaqvoCJapdTWjK8QI= -github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.29.1/go.mod h1:3KoRGkTH03W3QcwPsU9HEYs9qIG1LDjBaCuOctrETqk= -github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 h1:G6+UzGvubaet9QOh0664E9JeT+b6Zvop3AChozRqkrA= -github.com/aws/aws-sdk-go-v2/service/iam v1.42.0/go.mod h1:mPJkGQzeCoPs82ElNILor2JzZgYENr4UaSKUT8K27+c= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15 h1:M1R1rud7HzDrfCdlBQ7NjnRsDNEhXO/vGhuD189Ggmk= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15/go.mod h1:uvFKBSq9yMPV4LGAi7N4awn4tLY+hKE35f8THes2mzQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.2 h1:oxmDEO14NBZJbK/M8y3brhMFEIGN4j8a6Aq8eY0sqlo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.2/go.mod h1:4hH+8QCrk1uRWDPsVfsNDUup3taAjO8Dnx63au7smAU= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.37.0 h1:fC0s79wxfsbz/4WCvosbHLk2mb9ICjPyB+lWs6a0TGM= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.37.0/go.mod h1:6HxvKCop1trgfFlQGQmlq+WbMM5yPazMN9ClWFWGtDM= -github.com/aws/aws-sdk-go-v2/service/sns v1.34.4 h1:ihddI5wufQQCJiujUgAvWRqZcfDmSKIfXlAuX7T95cg= -github.com/aws/aws-sdk-go-v2/service/sns v1.34.4/go.mod h1:PJtxxMdj747j8DeZENRTTYAz/lx/pADn/U0k7YNNiUY= -github.com/aws/aws-sdk-go-v2/service/sqs v1.38.6 h1:XwpzAaL0nKdSvDS0SRGIQWkqpS8DjcyBRJcatPBFijY= -github.com/aws/aws-sdk-go-v2/service/sqs v1.38.6/go.mod h1:Bar4MrRxeqdn6XIh8JGfiXuFRmyrrsZNTJotxEJmWW0= -github.com/aws/aws-sdk-go-v2/service/ssm v1.61.1 h1:Pu5hveFc6RslFZP61W5SEMOoPd6RR2yrOu11ZxCkr+Y= -github.com/aws/aws-sdk-go-v2/service/ssm v1.61.1/go.mod h1:8OOmGP4EK2O8eJIKIgTUXTfznuhC1BBarYzb+B5ep44= -github.com/aws/aws-sdk-go-v2/service/sso v1.27.0 h1:j7/jTOjWeJDolPwZ/J4yZ7dUsxsWZEsxNwH5O7F8eEA= -github.com/aws/aws-sdk-go-v2/service/sso v1.27.0/go.mod h1:M0xdEPQtgpNT7kdAX4/vOAPkFj60hSQRb7TvW9B0iug= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.32.0 h1:ywQF2N4VjqX+Psw+jLjMmUL2g1RDHlvri3NxHA08MGI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.32.0/go.mod h1:Z+qv5Q6b7sWiclvbJyPSOT1BRVU9wfSUPaqQzZ1Xg3E= -github.com/aws/aws-sdk-go-v2/service/sts v1.36.0 h1:bRP/a9llXSSgDPk7Rqn5GD/DQCGo6uk95plBFKoXt2M= -github.com/aws/aws-sdk-go-v2/service/sts v1.36.0/go.mod h1:tgBsFzxwl65BWkuJ/x2EUs59bD4SfYKgikvFDJi1S58= -github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= -github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= +github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= +github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= +github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 h1:gx1AwW1Iyk9Z9dD9F4akX5gnN3QZwUB20GGKH/I+Rho= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10/go.mod h1:qqY157uZoqm5OXq/amuaBJyC9hgBCBQnsaWnPe905GY= +github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU= +github.com/aws/aws-sdk-go-v2/config v1.32.17/go.mod h1:OXqUMzgXytfoF9JaKkhrOYsyh72t9G+MJH8mMRaexOE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16 h1:r3RJBuU7X9ibt8RHbMjWE6y60QbKBiII6wSrXnapxSU= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16/go.mod h1:6cx7zqDENJDbBIIWX6P8s0h6hqHC8Avbjh9Dseo27ug= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.18 h1:9XFUd2lkr7VrbE4Qtrhm7AtNhGgZeGFI5QLZtQIflj8= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.18/go.mod h1:trImuKdWelQIJALvyGj6sKolJ1W8t628JOoTdDGVL9Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3 h1:XgjzLEE8CrNYnr4Xmi1W5PfKsKMjp4Pu1rWkJNO43JI= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3/go.mod h1:r7sfLXEN8RUA89tAHy1E7lCtVOOWIkqVy/FbnUdxW1E= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.301.0 h1:U+cZAMc8mN0jne8/ae7KrrFuILTXrZReAvc6BIpXGls= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.301.0/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY= +github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.32.22 h1:wc+/Ueo9HO1HbQGoYzjoozB3Zk4hJ67ykgyZC5yMEJ8= +github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.32.22/go.mod h1:yzDJW0Xp6ZPFise7iBYVjuRhAva8b7u9rYoVnE+xPi4= +github.com/aws/aws-sdk-go-v2/service/iam v1.53.10 h1:kcN3I3llO7VwIY5w3Pc5FmEonpsr23Ou7Cwk4qf7dik= +github.com/aws/aws-sdk-go-v2/service/iam v1.53.10/go.mod h1:1vkJzjCYC3byO0kIrBqLPzvZpuvYhPXkuyARs6E7tM4= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 h1:ieLCO1JxUWuxTZ1cRd0GAaeX7O6cIxnwk7tc1LsQhC4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15/go.mod h1:e3IzZvQ3kAWNykvE0Tr0RDZCMFInMvhku3qNpcIQXhM= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.23 h1:3Eo/PBBnjFi1+gYfaL286dpmFSW3mTfodBIybq36Qv4= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.23/go.mod h1:3oh+5xGSd1iuxonVb3Qbm+WJYlbhczT9kbzr6doJLzY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 h1:03xatSQO4+AM1lTAbnRg5OK528EUg744nW7F73U8DKw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23/go.mod h1:M8l3mwgx5ToK7wot2sBBce/ojzgnPzZXUV445gTSyE8= +github.com/aws/aws-sdk-go-v2/service/route53 v1.62.5 h1:Z+/OLsb85Kpq7TVLCspskqePaf68Tdv6GfmJP4kH6i0= +github.com/aws/aws-sdk-go-v2/service/route53 v1.62.5/go.mod h1:TmxGowuBYwjmHFOsEDxaZdsQE62JJzOmtiWafTi/czg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 h1:etqBTKY581iwLL/H/S2sVgk3C9lAsTJFeXWFDsDcWOU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.7 h1:JUGKqUnJHbXpS8uyuICP/zpQ+vXUIXW2zTEqjMLCqrY= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.7/go.mod h1:l/cqI7ujYqBuTR6Ll13d9/gG/uUdlVzJ1UDltEEBTOo= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= +github.com/aws/aws-sdk-go-v2/service/sns v1.39.17 h1:synXIPC/L4Cc489P0XDcrVJzHSLj7krKRpFLalbGM2k= +github.com/aws/aws-sdk-go-v2/service/sns v1.39.17/go.mod h1:4ABZnI23uNK37waIjGwkubnCwGhepIt9x1GvASfljJA= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.27 h1:QgaWXVmNDxv/U/3UIHfGb7ohvtFgerf/bYcYylj4i8E= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.27/go.mod h1:8S6ExnLprS0oIeA8ZlHkJUJ0BMpKqnRPws/S0jegTqQ= +github.com/aws/aws-sdk-go-v2/service/ssm v1.68.6 h1:0LPJjbSNEDHidGOXa0LfvSVbdn9/GdlJUQTgE0kFpso= +github.com/aws/aws-sdk-go-v2/service/ssm v1.68.6/go.mod h1:SrZAopBP5/lyQ6NBVXKlRp8wPIXhzBCZU98sEozmv8Y= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29h8BvsCoHQEQ6ST9X8w7w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= +github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= +github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bodgit/ntlmssp v0.0.0-20240506230425-31973bb52d9b h1:baFN6AnR0SeC194X2D292IUZcHDs4JjStpqtE70fjXE= github.com/bodgit/ntlmssp v0.0.0-20240506230425-31973bb52d9b/go.mod h1:Ram6ngyPDmP+0t6+4T2rymv0w0BS9N8Ch5vvUJccw5o= github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -128,28 +138,27 @@ github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURU github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ= github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6 h1:zWydSUQBJApHwpQ4guHi+mGyQN/8yN6xbKWdDtL3ZNM= github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6/go.mod h1:6BLLhzn1VEiJ4veuAGhINBTrBlV889Wd+aU4auxKOww= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= -github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= -github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= -github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -157,18 +166,17 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= -github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -177,114 +185,107 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= -github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas= +github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/hashicorp/aws-sdk-go-base v0.7.1 h1:7s/aR3hFn74tYPVihzDyZe7y/+BorN70rr9ZvpV3j3o= -github.com/hashicorp/aws-sdk-go-base v0.7.1/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65 h1:81+kWbE1yErFBMjME0I5k3x3kojjKsWtPYHEAutoPow= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65/go.mod h1:WtMzv9T++tfWVea+qB2MXoaqxw33S8bpJslzUike2mQ= -github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= -github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= -github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= -github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= +github.com/hashicorp/aws-sdk-go-base v1.1.0 h1:27urM3JAp6v+Oj/Ea5ULZwuFPK9cO1RUdEpV+rNdSAc= +github.com/hashicorp/aws-sdk-go-base v1.1.0/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= +github.com/hashicorp/consul/api v1.34.2 h1:B5jqSSKwWyY8U8WiGS5vmPEPkkF0bAvrECykdZkDR80= +github.com/hashicorp/consul/api v1.34.2/go.mod h1:+gAdHQa2zvgYX3ZfcgITtnYCSj6AgS/cgotvCKaE+b8= +github.com/hashicorp/consul/sdk v0.18.1 h1:RDTeBvAeOveI2xI86sV+8WkaN7OkP4zz+cG3fOobDCM= +github.com/hashicorp/consul/sdk v0.18.1/go.mod h1:XdP2tEJmAvlK4jgoKTTtohGkRJlS4mU44mv9/sjU21s= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter/gcs/v2 v2.2.2 h1:KDbsz44Clh+qpsskK9EnlhWki8NMH18jlAjEseJXIco= -github.com/hashicorp/go-getter/gcs/v2 v2.2.2/go.mod h1:reRiCTBtE1ANT92nMmjwbDzoB6KMJ5azAoMOvQRGGH0= -github.com/hashicorp/go-getter/s3/v2 v2.2.2 h1:ProI1SMBNRt17gC3I8XCMdh35sXN68IUieYnWXwfwew= -github.com/hashicorp/go-getter/s3/v2 v2.2.2/go.mod h1:5MRjeGjI4DqzkRYa+g6OuNJDR0MamdE5VqDPdI42+vQ= -github.com/hashicorp/go-getter/v2 v2.2.2 h1:Al5bzCNW5DrlZMK6TumGrSue7Xz8beyLcen+4N4erwo= -github.com/hashicorp/go-getter/v2 v2.2.2/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY= +github.com/hashicorp/go-getter/gcs/v2 v2.2.3 h1:m/KO1hAqSrL8sH91c7uyJzVhRtfk0GtRD+jU6Buy3nc= +github.com/hashicorp/go-getter/gcs/v2 v2.2.3/go.mod h1:HFbVYUSI6RERon4TTKpsloiYMnFYYGuJu0EaWUTfb9w= +github.com/hashicorp/go-getter/s3/v2 v2.2.3 h1:H2C6b9n1NyKiuxqpAbF3pIOMKSD2efy0vmtyC7khPrQ= +github.com/hashicorp/go-getter/s3/v2 v2.2.3/go.mod h1:SZQ4oeqBoOAoYfrUZ35PT6WcCeGeBHd22ZnI/yG2Iyo= +github.com/hashicorp/go-getter/v2 v2.2.3 h1:6CVzhT0KJQHqd9b0pK3xSP0CM/Cv+bVhk+jcaRJ2pGk= +github.com/hashicorp/go-getter/v2 v2.2.3/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-metrics v0.5.1 h1:rfPwUqFU6uZXNvGl4hzjY8LEBsqFVU4si1H9/Hqck/U= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6elejKY= +github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0= +github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= -github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/packer-plugin-sdk v0.6.8 h1:uBINKQOqcxb9ERgWm16Rdbcxj91Iyq2g1RVCuUsEN7I= -github.com/hashicorp/packer-plugin-sdk v0.6.8/go.mod h1:TvwlqryoWOljacuCtF5SKOg3Kz2sgydRVJzqY/S3PkY= -github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= -github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= -github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= -github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/memberlist v0.5.2 h1:rJoNPWZ0juJBgqn48gjy59K5H4rNgvUoM1kUD7bXiuI= +github.com/hashicorp/memberlist v0.5.2/go.mod h1:Ri9p/tRShbjYnpNf4FFPXG7wxEGY4Nrcn6E7jrVa//4= +github.com/hashicorp/packer-plugin-sdk v0.6.7 h1:R6xO8j5GUT1AC+1CmDvXCjjiCDndWbIA1O7jJ3MeTVs= +github.com/hashicorp/packer-plugin-sdk v0.6.7/go.mod h1:J+hZE+SdN0MPCZLmoRPSrqg4YuP/mXTuuVqiAYbDVfw= +github.com/hashicorp/serf v0.10.2 h1:m5IORhuNSjaxeljg5DeQVDlQyVkhRIjJDimbkCa8aAc= +github.com/hashicorp/serf v0.10.2/go.mod h1:T1CmSGfSeGfnfNy/w0odXQUR1rfECGd2Qdsp84DjOiY= +github.com/hashicorp/terraform-plugin-log v0.10.0 h1:eu2kW6/QBVdN4P3Ju2WiB2W3ObjkAsyfBsL3Wh1fj3g= +github.com/hashicorp/terraform-plugin-log v0.10.0/go.mod h1:/9RR5Cv2aAbrqcTSdNmY1NRHP4E3ekrXRGjqORpXyB0= +github.com/hashicorp/vault/api v1.23.0 h1:gXgluBsSECfRWTSW9niY2jwg2e9mMJc4WoHNv4g3h6A= +github.com/hashicorp/vault/api v1.23.0/go.mod h1:zransKiB9ftp+kgY8ydjnvCU7Wk8i9L0DYWpXeMj9ko= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= @@ -304,12 +305,17 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= -github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= +github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -322,94 +328,86 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg= github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= -github.com/masterzen/winrm v0.0.0-20250927112105-5f8e6c707321 h1:AKIJL2PfBX2uie0Mn5pxtG1+zut3hAVMZbRfoXecFzI= -github.com/masterzen/winrm v0.0.0-20250927112105-5f8e6c707321/go.mod h1:JajVhkiG2bYSNYYPYuWG7WZHr42CTjMTcCjfInRNCqc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/masterzen/winrm v0.0.0-20260407182533-5570be7f80cf h1:UxGs98qiSWMqoqQsJxSW4FzCRdPPUFCraQ74ufgmISI= +github.com/masterzen/winrm v0.0.0-20260407182533-5570be7f80cf/go.mod h1:JajVhkiG2bYSNYYPYuWG7WZHr42CTjMTcCjfInRNCqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= +github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff h1:bFJ74ac7ZK/jyislqiWdzrnENesFt43sNEBRh1xk/+g= github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/nywilken/go-cty v1.13.3 h1:03U99oXf3j3g9xgqAE3YGpixCjM8Mg09KZ0Ji9LzX0o= github.com/nywilken/go-cty v1.13.3/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= -github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db h1:9uViuKtx1jrlXLBW/pMnhOfzn3iSEdLase/But/IZRU= -github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/packer-community/winrmcp v0.0.0-20221126162354-6e900dd2c68f h1:sWm3fnjG6kxvDuGiQf46Io5xCTj3QJfNJIeICJ4g1kw= +github.com/packer-community/winrmcp v0.0.0-20221126162354-6e900dd2c68f/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.2 h1:taJnKntsWgU+qae21Rx52lIwndAdKrj0mfUNQsz1z4Q= -github.com/pkg/sftp v1.13.2/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8= +github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU= +github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -420,8 +418,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -431,179 +427,144 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde h1:AMNpJRc7P+GTwVbl8DkK2I9I8BBUzNiHuH/tlxrpan0= github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde/go.mod h1:MvrEmduDUz4ST5pGZ7CABCnOU5f3ZiOAZzT6b1A6nX8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= -github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= -github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= +github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= +github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.61.0 h1:lR4WnQLBC9XyTwKrz0327rq2QnIdJNpaVIGuW2yMvME= -go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.61.0/go.mod h1:UK49mXgwqIWFUDH8ibqTswbhy4fuwjEjj4VKMC7krUQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= +go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.68.0 h1:AojZNtrcbjp4Ty3ZwpQvPCcoM5o5CApjf1kj3XrOLdw= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.68.0/go.mod h1:AXXwEDlD/ZZwps0zPtTuU2K05sf55/6GLnQ21L0WzFo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= -go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw= +golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= +golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/api v0.230.0 h1:2u1hni3E+UXAXrONrrkfWpi/V6cyKVAbfGVeGtC3OxM= -google.golang.org/api v0.230.0/go.mod h1:aqvtoMk7YkiXx+6U12arQFExiRV9D/ekvMCwCd/TksQ= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.278.0 h1:W7jiRvRi53VYFfZ/HoZjQBtJk7gOFbHD8ot1RzVZU6E= +google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348 h1:JjVGDZYWkJWZcxveJGzfkXC5myDVWAd4dZdgbzrDUv8= +google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348/go.mod h1:95PqD4xM+AdOcBGsmgfaofXsiA37uXDtDufVbntT3TU= +google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 h1:U8orV30l6KpDsi9dxU0CoJZGbjS8EEpw+6ba+XwGPQA= +google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348/go.mod h1:Yzdzr5OOZFgSsEV2D/Xi9NL3bszpXFAg0hFJiRohcD8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 h1:pfIbyB44sWzHiCpRqIen67ZQnVXSfIxWrqUMk1qwODE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -619,5 +580,3 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 4c514fc73587fe651d6b945fbee4dd155475c727 Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Wed, 13 May 2026 20:48:49 +0200 Subject: [PATCH 2/8] feat: Use AWS SDK 2 only - part 2 --- builder/chroot/builder.hcl2spec.go | 15 ++- builder/chroot/step_attach_volume.go | 6 +- builder/chroot/step_create_volume_test.go | 2 +- builder/common/block_device.hcl2spec.go | 23 ++-- builder/common/helper_funcs.go | 2 - builder/common/run_config.go | 2 +- builder/common/run_config.hcl2spec.go | 7 +- builder/common/snapshot_config.go | 4 +- builder/common/state.hcl2spec.go | 2 + builder/common/step_enable_deprecation.go | 4 +- .../step_enable_deregistration_protection.go | 6 +- builder/common/step_iam_instance_profile.go | 86 +++++++----- builder/common/step_key_pair.go | 18 +-- builder/common/step_key_pair_test.go | 11 +- builder/common/step_modify_ami_attributes.go | 98 +++++++------- builder/common/step_modify_ebs_instance.go | 13 +- builder/common/step_network_info_test.go | 125 +++++++++--------- builder/common/step_pre_validate.go | 38 +++--- builder/common/step_pre_validate_test.go | 4 +- builder/common/step_run_spot_instance.go | 4 +- builder/common/step_security_group.go | 95 ++++--------- builder/common/step_source_ami_info_test.go | 19 ++- builder/common/tags.go | 8 +- builder/instance/builder.hcl2spec.go | 17 +-- .../builder/chroot/Config-not-required.mdx | 10 +- .../builder/common/AMIConfig-not-required.mdx | 4 +- .../common/AWSPollingConfig-not-required.mdx | 5 + .../common/BlockDevice-not-required.mdx | 8 +- .../builder/common/Placement-not-required.mdx | 2 +- .../builder/common/RunConfig-not-required.mdx | 8 +- .../builder/common/RunConfig-required.mdx | 2 +- .../volumeAttachedDetachedWaiterOptions.mdx | 5 + .../builder/instance/Config-not-required.mdx | 2 +- go.mod | 1 - go.sum | 8 -- 35 files changed, 327 insertions(+), 337 deletions(-) create mode 100644 docs-partials/builder/common/volumeAttachedDetachedWaiterOptions.mdx diff --git a/builder/chroot/builder.hcl2spec.go b/builder/chroot/builder.hcl2spec.go index 19f505bc..6b4eb85e 100644 --- a/builder/chroot/builder.hcl2spec.go +++ b/builder/chroot/builder.hcl2spec.go @@ -3,6 +3,7 @@ package chroot import ( + "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer-plugin-amazon/builder/common" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -22,7 +23,7 @@ type FlatConfig struct { PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"` 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"` + AMIVirtType *types.VirtualizationType `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"` AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users" hcl:"ami_users"` AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups" hcl:"ami_groups"` AMIOrgArns []string `mapstructure:"ami_org_arns" required:"false" cty:"ami_org_arns" hcl:"ami_org_arns"` @@ -41,7 +42,7 @@ type FlatConfig struct { AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids" hcl:"region_kms_key_ids"` AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region" hcl:"skip_save_build_region"` AMISnapshotCopyDurationMinutes *int64 `mapstructure:"snapshot_copy_duration_minutes" required:"false" cty:"snapshot_copy_duration_minutes" hcl:"snapshot_copy_duration_minutes"` - AMIIMDSSupport *string `mapstructure:"imds_support" required:"false" cty:"imds_support" hcl:"imds_support"` + AMIIMDSSupport *types.ImdsSupportValues `mapstructure:"imds_support" required:"false" cty:"imds_support" hcl:"imds_support"` DeprecationTime *string `mapstructure:"deprecate_at" cty:"deprecate_at" hcl:"deprecate_at"` SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"` SnapshotTag []config.FlatKeyValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag" hcl:"snapshot_tag"` @@ -77,18 +78,18 @@ type FlatConfig struct { PostMountCommands []string `mapstructure:"post_mount_commands" required:"false" cty:"post_mount_commands" hcl:"post_mount_commands"` PreMountCommands []string `mapstructure:"pre_mount_commands" required:"false" cty:"pre_mount_commands" hcl:"pre_mount_commands"` RootDeviceName *string `mapstructure:"root_device_name" required:"false" cty:"root_device_name" hcl:"root_device_name"` - RootVolumeSize *int64 `mapstructure:"root_volume_size" required:"false" cty:"root_volume_size" hcl:"root_volume_size"` - RootVolumeType *string `mapstructure:"root_volume_type" required:"false" cty:"root_volume_type" hcl:"root_volume_type"` + RootVolumeSize *int32 `mapstructure:"root_volume_size" required:"false" cty:"root_volume_size" hcl:"root_volume_size"` + RootVolumeType *types.VolumeType `mapstructure:"root_volume_type" required:"false" cty:"root_volume_type" hcl:"root_volume_type"` SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"` SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"` RootVolumeTags map[string]string `mapstructure:"root_volume_tags" required:"false" cty:"root_volume_tags" hcl:"root_volume_tags"` RootVolumeTag []config.FlatKeyValue `mapstructure:"root_volume_tag" required:"false" cty:"root_volume_tag" hcl:"root_volume_tag"` RootVolumeEncryptBoot *bool `mapstructure:"root_volume_encrypt_boot" required:"false" cty:"root_volume_encrypt_boot" hcl:"root_volume_encrypt_boot"` RootVolumeKmsKeyId *string `mapstructure:"root_volume_kms_key_id" required:"false" cty:"root_volume_kms_key_id" hcl:"root_volume_kms_key_id"` - Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture" hcl:"ami_architecture"` - BootMode *string `mapstructure:"boot_mode" required:"false" cty:"boot_mode" hcl:"boot_mode"` + Architecture *types.ArchitectureValues `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture" hcl:"ami_architecture"` + BootMode *types.BootModeValues `mapstructure:"boot_mode" required:"false" cty:"boot_mode" hcl:"boot_mode"` UefiData *string `mapstructure:"uefi_data" required:"false" cty:"uefi_data" hcl:"uefi_data"` - TpmSupport *string `mapstructure:"tpm_support" required:"false" cty:"tpm_support" hcl:"tpm_support"` + TpmSupport *types.TpmSupportValues `mapstructure:"tpm_support" required:"false" cty:"tpm_support" hcl:"tpm_support"` } // FlatMapstructure returns a new FlatConfig. diff --git a/builder/chroot/step_attach_volume.go b/builder/chroot/step_attach_volume.go index 49334cb7..566d9c97 100644 --- a/builder/chroot/step_attach_volume.go +++ b/builder/chroot/step_attach_volume.go @@ -71,20 +71,20 @@ func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) mu } func (s *StepAttachVolume) Cleanup(state multistep.StateBag) { - ctx := state.Get("context").(context.Context) ui := state.Get("ui").(packersdk.Ui) - if err := s.CleanupFunc(ctx, state); err != nil { + if err := s.CleanupFunc(state); err != nil { ui.Error(err.Error()) } } -func (s *StepAttachVolume) CleanupFunc(ctx context.Context, state multistep.StateBag) error { +func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error { if !s.attached { return nil } ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) + ctx := state.Get("context").(context.Context) ui.Say("Detaching EBS volume...") _, err := ec2conn.DetachVolume(ctx, &ec2.DetachVolumeInput{VolumeId: &s.volumeId}) diff --git a/builder/chroot/step_create_volume_test.go b/builder/chroot/step_create_volume_test.go index c74e8305..7b5aefa1 100644 --- a/builder/chroot/step_create_volume_test.go +++ b/builder/chroot/step_create_volume_test.go @@ -55,7 +55,7 @@ func TestCreateVolume_io1_to_io1(t *testing.T) { ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice) assert.NoError(t, err) assert.Equal(t, ret.VolumeType, stepCreateVolume.RootVolumeType) - assert.Equal(t, ret.Iops, *testRootDevice.Ebs.Iops) + assert.Equal(t, *ret.Iops, *testRootDevice.Ebs.Iops) } func TestCreateVolume_io1_to_gp2(t *testing.T) { diff --git a/builder/common/block_device.hcl2spec.go b/builder/common/block_device.hcl2spec.go index 5f5c3f06..5be924cf 100644 --- a/builder/common/block_device.hcl2spec.go +++ b/builder/common/block_device.hcl2spec.go @@ -3,6 +3,7 @@ package common import ( + "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/hcl/v2/hcldec" "github.com/zclconf/go-cty/cty" ) @@ -10,17 +11,17 @@ import ( // FlatBlockDevice is an auto-generated flat version of BlockDevice. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatBlockDevice struct { - DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"` - DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"` - Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"` - IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"` - NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"` - SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"` - Throughput *int64 `mapstructure:"throughput" required:"false" cty:"throughput" hcl:"throughput"` - VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"` - VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"` - VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"` - KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"` + DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"` + DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"` + Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"` + IOPS *int32 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"` + NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"` + SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"` + Throughput *int32 `mapstructure:"throughput" required:"false" cty:"throughput" hcl:"throughput"` + VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"` + VolumeType *types.VolumeType `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"` + VolumeSize *int32 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"` + KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"` } // FlatMapstructure returns a new FlatBlockDevice. diff --git a/builder/common/helper_funcs.go b/builder/common/helper_funcs.go index d29f41fd..b1a1c7ea 100644 --- a/builder/common/helper_funcs.go +++ b/builder/common/helper_funcs.go @@ -29,8 +29,6 @@ func DestroyAMIs(ctx context.Context, imageids []string, ec2conn clients.Ec2Clie // Deregister image by name. for _, i := range resp.Images { - - ctx := context.TODO() err = retry.Config{ Tries: 11, ShouldRetry: func(err error) bool { diff --git a/builder/common/run_config.go b/builder/common/run_config.go index e3bf0f48..6b79542d 100644 --- a/builder/common/run_config.go +++ b/builder/common/run_config.go @@ -418,7 +418,7 @@ type RunConfig struct { // This feature exists to help prevent situations where a Packer build fails // because a particular availability zone does not have capacity for the // specific instance_type requested in instance_type. - SpotInstanceTypes []ec2types.InstanceType `mapstructure:"spot_instance_types" required:"false"` + SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false"` // With Spot Instances, you pay the Spot price that's in effect for the // time period your instances are running. Spot Instance prices are set by // Amazon EC2 and adjust gradually based on long-term trends in supply and diff --git a/builder/common/run_config.hcl2spec.go b/builder/common/run_config.hcl2spec.go index 565b2d67..340efe1b 100644 --- a/builder/common/run_config.hcl2spec.go +++ b/builder/common/run_config.hcl2spec.go @@ -3,6 +3,7 @@ package common import ( + "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/zclconf/go-cty/cty" @@ -115,9 +116,9 @@ func (*FlatMetadataOptions) HCL2Spec() map[string]hcldec.Spec { // FlatPlacement is an auto-generated flat version of Placement. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatPlacement struct { - HostResourceGroupArn *string `mapstructure:"host_resource_group_arn" required:"false" cty:"host_resource_group_arn" hcl:"host_resource_group_arn"` - HostId *string `mapstructure:"host_id" required:"false" cty:"host_id" hcl:"host_id"` - Tenancy *string `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"` + HostResourceGroupArn *string `mapstructure:"host_resource_group_arn" required:"false" cty:"host_resource_group_arn" hcl:"host_resource_group_arn"` + HostId *string `mapstructure:"host_id" required:"false" cty:"host_id" hcl:"host_id"` + Tenancy *types.Tenancy `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"` } // FlatMapstructure returns a new FlatPlacement. diff --git a/builder/common/snapshot_config.go b/builder/common/snapshot_config.go index fc34c619..1d2ad915 100644 --- a/builder/common/snapshot_config.go +++ b/builder/common/snapshot_config.go @@ -5,7 +5,9 @@ package common -import "github.com/hashicorp/packer-plugin-sdk/template/config" +import ( + "github.com/hashicorp/packer-plugin-sdk/template/config" +) // SnapshotConfig is for common configuration related to creating AMIs. type SnapshotConfig struct { diff --git a/builder/common/state.hcl2spec.go b/builder/common/state.hcl2spec.go index 30a21bd1..055d3e6b 100644 --- a/builder/common/state.hcl2spec.go +++ b/builder/common/state.hcl2spec.go @@ -12,6 +12,7 @@ import ( 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"` + MaxTimeout *int `mapstructure:"max_timeout" required:"false" cty:"max_timeout" hcl:"max_timeout"` } // FlatMapstructure returns a new FlatAWSPollingConfig. @@ -28,6 +29,7 @@ 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}, + "max_timeout": &hcldec.AttrSpec{Name: "max_timeout", Type: cty.Number, Required: false}, } return s } diff --git a/builder/common/step_enable_deprecation.go b/builder/common/step_enable_deprecation.go index 49f655d7..deda3cba 100644 --- a/builder/common/step_enable_deprecation.go +++ b/builder/common/step_enable_deprecation.go @@ -38,7 +38,7 @@ func (s *StepEnableDeprecation) Run(ctx context.Context, state multistep.StateBa for region, ami := range amis { ui.Say(fmt.Sprintf("Enabling deprecation on AMI (%s) in region %q ...", ami, region)) - conn, err := GetRegionConn(ctx, s.AccessConfig, region) + conn, err := GetEc2Client(ctx, s.AccessConfig, region) if err != nil { err := fmt.Errorf("failed to connect to region %s: %s", region, err) state.Put("error", err.Error()) @@ -46,7 +46,7 @@ func (s *StepEnableDeprecation) Run(ctx context.Context, state multistep.StateBa return multistep.ActionHalt } - _, err = conn.EnableImageDeprecation(&ec2.EnableImageDeprecationInput{ + _, err = conn.EnableImageDeprecation(ctx, &ec2.EnableImageDeprecationInput{ ImageId: &ami, DeprecateAt: &deprecationTime, }) diff --git a/builder/common/step_enable_deregistration_protection.go b/builder/common/step_enable_deregistration_protection.go index 03317332..8744b1af 100644 --- a/builder/common/step_enable_deregistration_protection.go +++ b/builder/common/step_enable_deregistration_protection.go @@ -8,7 +8,7 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -42,7 +42,7 @@ func (s *StepEnableDeregistrationProtection) Run(ctx context.Context, state mult for region, ami := range amis { log.Printf("Enabling deregistration protection on AMI (%s) in region %q ...", ami, region) - conn, err := GetRegionConn(s.AccessConfig, region) + conn, err := GetEc2Client(ctx, s.AccessConfig, region) if err != nil { err := fmt.Errorf("failed to connect to region %s: %s", region, err) state.Put("error", err.Error()) @@ -50,7 +50,7 @@ func (s *StepEnableDeregistrationProtection) Run(ctx context.Context, state mult return multistep.ActionHalt } - _, err = conn.EnableImageDeregistrationProtection(&ec2.EnableImageDeregistrationProtectionInput{ + _, err = conn.EnableImageDeregistrationProtection(ctx, &ec2.EnableImageDeregistrationProtectionInput{ ImageId: &ami, WithCooldown: &s.DeregistrationProtection.WithCooldown, }) diff --git a/builder/common/step_iam_instance_profile.go b/builder/common/step_iam_instance_profile.go index 5c08f89f..8017466c 100644 --- a/builder/common/step_iam_instance_profile.go +++ b/builder/common/step_iam_instance_profile.go @@ -6,13 +6,16 @@ package common import ( "context" "encoding/json" + "errors" "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer-plugin-sdk/retry" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" "github.com/hashicorp/packer-plugin-sdk/uuid" ) @@ -31,17 +34,16 @@ type StepIamInstanceProfile struct { } func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - iamsvc := state.Get("iam").(*iam.IAM) + iamsvc := state.Get("iam").(*iam.Client) ui := state.Get("ui").(packersdk.Ui) state.Put("iamInstanceProfile", "") if len(s.IamInstanceProfile) > 0 { if !s.SkipProfileValidation { - _, err := iamsvc.GetInstanceProfile( - &iam.GetInstanceProfileInput{ - InstanceProfileName: aws.String(s.IamInstanceProfile), - }, + _, err := iamsvc.GetInstanceProfile(ctx, &iam.GetInstanceProfileInput{ + InstanceProfileName: aws.String(s.IamInstanceProfile), + }, ) if err != nil { err := fmt.Errorf("Couldn't find specified instance profile: %s", err) @@ -75,7 +77,7 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB state.Put("error", err) return multistep.ActionHalt } - profileResp, err := iamsvc.CreateInstanceProfile(&iam.CreateInstanceProfileInput{ + profileResp, err := iamsvc.CreateInstanceProfile(ctx, &iam.CreateInstanceProfileInput{ InstanceProfileName: aws.String(profileName), Tags: iamProfileTags, }) @@ -84,13 +86,25 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB state.Put("error", err) return multistep.ActionHalt } - s.createdInstanceProfileName = aws.StringValue(profileResp.InstanceProfile.InstanceProfileName) + s.createdInstanceProfileName = aws.ToString(profileResp.InstanceProfile.InstanceProfileName) log.Printf("[DEBUG] Waiting for temporary instance profile: %s", s.createdInstanceProfileName) - err = iamsvc.WaitUntilInstanceProfileExists(&iam.GetInstanceProfileInput{ - InstanceProfileName: aws.String(s.createdInstanceProfileName), + err = retry.Config{ + Tries: 40, + ShouldRetry: func(err error) bool { + if err == nil { + return false + } + log.Printf("[DEBUG] Waiting for instance profile %s to be available: %s", s.createdInstanceProfileName, err.Error()) + var nse *iamtypes.NoSuchEntityException + return errors.As(err, &nse) + }, + }.Run(ctx, func(ctx context.Context) error { + _, err := iamsvc.GetInstanceProfile(ctx, &iam.GetInstanceProfileInput{ + InstanceProfileName: aws.String(s.createdInstanceProfileName), + }) + return err }) - if err == nil { log.Printf("[DEBUG] Found instance profile %s", s.createdInstanceProfileName) } else { @@ -102,7 +116,7 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB ui.Say(fmt.Sprintf("Creating temporary role for this instance: %s", profileName)) - roleResp, err := iamsvc.CreateRole(&iam.CreateRoleInput{ + roleResp, err := iamsvc.CreateRole(ctx, &iam.CreateRoleInput{ RoleName: aws.String(profileName), Description: aws.String("Temporary role for Packer"), AssumeRolePolicyDocument: aws.String("{\"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Principal\": {\"Service\": \"ec2.amazonaws.com\"},\"Action\": \"sts:AssumeRole\"}]}"), @@ -114,16 +128,25 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB return multistep.ActionHalt } - s.createdRoleName = aws.StringValue(roleResp.Role.RoleName) - - log.Printf("[DEBUG] Waiting for temporary role: %s", s.createdInstanceProfileName) - err = iamsvc.WaitUntilRoleExistsWithContext( - aws.BackgroundContext(), - &iam.GetRoleInput{ - RoleName: aws.String(s.createdRoleName), + s.createdRoleName = aws.ToString(roleResp.Role.RoleName) + + log.Printf("[DEBUG] Waiting for temporary role: %s", s.createdRoleName) + err = retry.Config{ + Tries: 20, + ShouldRetry: func(err error) bool { + if err == nil { + return false + } + log.Printf("[DEBUG] Waiting for temporary role %s to be available: %s", s.createdRoleName, err.Error()) + var nse *iamtypes.NoSuchEntityException + return errors.As(err, &nse) }, - s.PollingConfig.getWaiterOptions()..., - ) + }.Run(ctx, func(ctx context.Context) error { + _, err := iamsvc.GetRole(ctx, &iam.GetRoleInput{ + RoleName: aws.String(s.createdRoleName), + }) + return err + }) if err == nil { log.Printf("[DEBUG] Found temporary role %s", s.createdRoleName) } else { @@ -135,7 +158,7 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB ui.Say(fmt.Sprintf("Attaching policy to the temporary role: %s", profileName)) - _, err = iamsvc.PutRolePolicy(&iam.PutRolePolicyInput{ + _, err = iamsvc.PutRolePolicy(ctx, &iam.PutRolePolicyInput{ RoleName: roleResp.Role.RoleName, PolicyName: aws.String(profileName), PolicyDocument: aws.String(string(policy)), @@ -146,9 +169,9 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB return multistep.ActionHalt } - s.createdPolicyName = aws.StringValue(roleResp.Role.RoleName) + s.createdPolicyName = aws.ToString(roleResp.Role.RoleName) - _, err = iamsvc.AddRoleToInstanceProfile(&iam.AddRoleToInstanceProfileInput{ + _, err = iamsvc.AddRoleToInstanceProfile(ctx, &iam.AddRoleToInstanceProfileInput{ RoleName: roleResp.Role.RoleName, InstanceProfileName: profileResp.InstanceProfile.InstanceProfileName, }) @@ -159,21 +182,22 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB } s.roleIsAttached = true - state.Put("iamInstanceProfile", aws.StringValue(profileResp.InstanceProfile.InstanceProfileName)) + state.Put("iamInstanceProfile", aws.ToString(profileResp.InstanceProfile.InstanceProfileName)) } return multistep.ActionContinue } func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) { - iamsvc := state.Get("iam").(*iam.IAM) + iamsvc := state.Get("iam").(*iam.Client) ui := state.Get("ui").(packersdk.Ui) + ctx := state.Get("ctx").(context.Context) var err error if s.roleIsAttached == true { ui.Say("Detaching temporary role from instance profile...") - _, err := iamsvc.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{ + _, err := iamsvc.RemoveRoleFromInstanceProfile(ctx, &iam.RemoveRoleFromInstanceProfileInput{ InstanceProfileName: aws.String(s.createdInstanceProfileName), RoleName: aws.String(s.createdRoleName), }) @@ -185,7 +209,7 @@ func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) { if s.createdPolicyName != "" { ui.Say("Removing policy from temporary role...") - _, _ = iamsvc.DeleteRolePolicy(&iam.DeleteRolePolicyInput{ + _, _ = iamsvc.DeleteRolePolicy(ctx, &iam.DeleteRolePolicyInput{ PolicyName: aws.String(s.createdPolicyName), RoleName: aws.String(s.createdRoleName), }) @@ -193,7 +217,7 @@ func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) { if s.createdRoleName != "" { ui.Say("Deleting temporary role...") - _, err = iamsvc.DeleteRole(&iam.DeleteRoleInput{RoleName: &s.createdRoleName}) + _, err = iamsvc.DeleteRole(ctx, &iam.DeleteRoleInput{RoleName: &s.createdRoleName}) if err != nil { ui.Error(fmt.Sprintf( "Error %s. Please delete the role manually: %s", err.Error(), s.createdRoleName)) @@ -203,7 +227,7 @@ func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) { if s.createdInstanceProfileName != "" { ui.Say("Deleting temporary instance profile...") - _, err = iamsvc.DeleteInstanceProfile(&iam.DeleteInstanceProfileInput{ + _, err = iamsvc.DeleteInstanceProfile(ctx, &iam.DeleteInstanceProfileInput{ InstanceProfileName: &s.createdInstanceProfileName}) if err != nil { diff --git a/builder/common/step_key_pair.go b/builder/common/step_key_pair.go index 74efe054..61aea651 100644 --- a/builder/common/step_key_pair.go +++ b/builder/common/step_key_pair.go @@ -10,8 +10,9 @@ import ( "runtime" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" @@ -69,12 +70,12 @@ func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multist ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.Comm.SSHTemporaryKeyPairName)) keypair := &ec2.CreateKeyPairInput{ KeyName: &s.Comm.SSHTemporaryKeyPairName, - KeyType: &s.Comm.SSHTemporaryKeyPairType, + KeyType: ec2types.KeyType(s.Comm.SSHTemporaryKeyPairType), } if !s.IsRestricted { region := state.Get("region").(*string) - ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, aws.StringValue(region), state) + ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, aws.ToString(region), state) if err != nil { err := fmt.Errorf("Error tagging key pair: %s", err) state.Put("error", err) @@ -82,7 +83,7 @@ func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multist return multistep.ActionHalt } - keypair.TagSpecifications = ec2Tags.TagSpecifications(ec2.ResourceTypeKeyPair) + keypair.TagSpecifications = ec2Tags.TagSpecifications(ec2types.ResourceTypeKeyPair) } err := retry.Config{ @@ -90,7 +91,7 @@ func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multist RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { var err error - keyResp, err = ec2conn.CreateKeyPair(keypair) + keyResp, err = ec2conn.CreateKeyPair(ctx, keypair) return err }) @@ -139,12 +140,13 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) { return } - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) + ctx := state.Get("ctx").(context.Context) // Remove the keypair ui.Say("Deleting temporary keypair...") - _, err := ec2conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{KeyName: &s.Comm.SSHTemporaryKeyPairName}) + _, err := ec2conn.DeleteKeyPair(ctx, &ec2.DeleteKeyPairInput{KeyName: &s.Comm.SSHTemporaryKeyPairName}) if err != nil { ui.Error(fmt.Sprintf( "Error cleaning up keypair. Please delete the key manually: %s", s.Comm.SSHTemporaryKeyPairName)) diff --git a/builder/common/step_key_pair_test.go b/builder/common/step_key_pair_test.go index 37c59bc2..cab2c65c 100644 --- a/builder/common/step_key_pair_test.go +++ b/builder/common/step_key_pair_test.go @@ -9,8 +9,9 @@ import ( "sync" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" @@ -26,7 +27,7 @@ type mockEC2KeyPairConn struct { lock sync.Mutex } -func (m *mockEC2KeyPairConn) CreateKeyPair(keyPairInput *ec2.CreateKeyPairInput) (*ec2.CreateKeyPairOutput, error) { +func (m *mockEC2KeyPairConn) CreateKeyPair(ctx context.Context, keyPairInput *ec2.CreateKeyPairInput, optFns ...func(*ec2.Options)) (*ec2.CreateKeyPairOutput, error) { m.lock.Lock() m.CreateKeyPairCount++ m.CreateKeyPairArgs = append(m.CreateKeyPairArgs, *keyPairInput) @@ -79,7 +80,7 @@ func TestStepKeyPair_withDefault(t *testing.T) { t.Fatalf("Unexpected Key Type expected %s, got %s", "temp-key-name", *createKeyPairArgs[0].KeyName) } - if *createKeyPairArgs[0].KeyType != "rsa" { - t.Fatalf("Expeccted KeyType %s got %s", "rsa", *createKeyPairArgs[0].KeyType) + if createKeyPairArgs[0].KeyType != ec2types.KeyTypeRsa { + t.Fatalf("Expeccted KeyType %s got %s", "rsa", createKeyPairArgs[0].KeyType) } } diff --git a/builder/common/step_modify_ami_attributes.go b/builder/common/step_modify_ami_attributes.go index 4fdfd7ea..4d6338b6 100644 --- a/builder/common/step_modify_ami_attributes.go +++ b/builder/common/step_modify_ami_attributes.go @@ -10,8 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata" @@ -36,10 +34,8 @@ type StepModifyAMIAttributes struct { } func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(clients.Ec2Client) - session := state.Get("awsSession").(*session.Session) + awscfg := state.Get("awsConfig").(*aws.Config) ui := state.Get("ui").(packersdk.Ui) - config := state.Get("config").(*Config) if s.AMISkipCreateImage { ui.Say("Skipping AMI modify attributes...") @@ -66,7 +62,7 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State } var err error - s.Ctx.Data = extractBuildInfo(*ec2conn.Config.Region, state, s.GeneratedData) + s.Ctx.Data = extractBuildInfo(awscfg.Region, state, s.GeneratedData) s.Description, err = interpolate.Render(s.Description, &s.Ctx) if err != nil { err = fmt.Errorf("Error interpolating AMI description: %s", err) @@ -80,22 +76,22 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State options := make(map[string]*ec2.ModifyImageAttributeInput) if s.Description != "" { options["description"] = &ec2.ModifyImageAttributeInput{ - Description: &ec2.AttributeValue{Value: &s.Description}, + Description: &ec2types.AttributeValue{Value: &s.Description}, } } snapshotOptions := make(map[string]*ec2.ModifySnapshotAttributeInput) if len(s.Groups) > 0 { - groups := make([]*string, len(s.Groups)) - addsImage := make([]*ec2.LaunchPermission, len(s.Groups)) + groups := make([]string, len(s.Groups)) + addsImage := make([]ec2types.LaunchPermission, len(s.Groups)) addGroups := &ec2.ModifyImageAttributeInput{ - LaunchPermission: &ec2.LaunchPermissionModifications{}, + LaunchPermission: &ec2types.LaunchPermissionModifications{}, } for i, g := range s.Groups { - groups[i] = aws.String(g) - addsImage[i] = &ec2.LaunchPermission{ - Group: aws.String(g), + groups[i] = string(g) + addsImage[i] = ec2types.LaunchPermission{ + Group: ec2types.PermissionGroup(g), } } @@ -105,16 +101,16 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State } if len(s.SnapshotGroups) > 0 { - groups := make([]*string, len(s.SnapshotGroups)) - addsSnapshot := make([]*ec2.CreateVolumePermission, len(s.SnapshotGroups)) + groups := make([]string, len(s.SnapshotGroups)) + addsSnapshot := make([]ec2types.CreateVolumePermission, len(s.SnapshotGroups)) addSnapshotGroups := &ec2.ModifySnapshotAttributeInput{ - CreateVolumePermission: &ec2.CreateVolumePermissionModifications{}, + CreateVolumePermission: &ec2types.CreateVolumePermissionModifications{}, } for i, g := range s.SnapshotGroups { - groups[i] = aws.String(g) - addsSnapshot[i] = &ec2.CreateVolumePermission{ - Group: aws.String(g), + groups[i] = g + addsSnapshot[i] = ec2types.CreateVolumePermission{ + Group: ec2types.PermissionGroup(g), } } addSnapshotGroups.GroupNames = groups @@ -123,73 +119,73 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State } if len(s.Users) > 0 { - users := make([]*string, len(s.Users)) - addsImage := make([]*ec2.LaunchPermission, len(s.Users)) + users := make([]string, len(s.Users)) + addsImage := make([]ec2types.LaunchPermission, len(s.Users)) for i, u := range s.Users { - users[i] = aws.String(u) - addsImage[i] = &ec2.LaunchPermission{UserId: aws.String(u)} + users[i] = u + addsImage[i] = ec2types.LaunchPermission{UserId: &u} } options["users"] = &ec2.ModifyImageAttributeInput{ UserIds: users, - LaunchPermission: &ec2.LaunchPermissionModifications{ + LaunchPermission: &ec2types.LaunchPermissionModifications{ Add: addsImage, }, } } if len(s.SnapshotUsers) > 0 { - users := make([]*string, len(s.SnapshotUsers)) - addsSnapshot := make([]*ec2.CreateVolumePermission, len(s.SnapshotUsers)) + users := make([]string, len(s.SnapshotUsers)) + addsSnapshot := make([]ec2types.CreateVolumePermission, len(s.SnapshotUsers)) for i, u := range s.SnapshotUsers { - users[i] = aws.String(u) - addsSnapshot[i] = &ec2.CreateVolumePermission{UserId: aws.String(u)} + users[i] = u + addsSnapshot[i] = ec2types.CreateVolumePermission{UserId: &u} } snapshotOptions["users"] = &ec2.ModifySnapshotAttributeInput{ UserIds: users, - CreateVolumePermission: &ec2.CreateVolumePermissionModifications{ + CreateVolumePermission: &ec2types.CreateVolumePermissionModifications{ Add: addsSnapshot, }, } } if len(s.OrgArns) > 0 { - orgArns := make([]*string, len(s.OrgArns)) - addsImage := make([]*ec2.LaunchPermission, len(s.OrgArns)) + orgArns := make([]string, len(s.OrgArns)) + addsImage := make([]ec2types.LaunchPermission, len(s.OrgArns)) for i, u := range s.OrgArns { - orgArns[i] = aws.String(u) - addsImage[i] = &ec2.LaunchPermission{OrganizationArn: aws.String(u)} + orgArns[i] = u + addsImage[i] = ec2types.LaunchPermission{OrganizationArn: &u} } options["ami org arns"] = &ec2.ModifyImageAttributeInput{ OrganizationArns: orgArns, - LaunchPermission: &ec2.LaunchPermissionModifications{ + LaunchPermission: &ec2types.LaunchPermissionModifications{ Add: addsImage, }, } } if len(s.OuArns) > 0 { - ouArns := make([]*string, len(s.OuArns)) - addsImage := make([]*ec2.LaunchPermission, len(s.OuArns)) + ouArns := make([]string, len(s.OuArns)) + addsImage := make([]ec2types.LaunchPermission, len(s.OuArns)) for i, u := range s.OuArns { - ouArns[i] = aws.String(u) - addsImage[i] = &ec2.LaunchPermission{OrganizationalUnitArn: aws.String(u)} + ouArns[i] = u + addsImage[i] = ec2types.LaunchPermission{OrganizationalUnitArn: &u} } options["ami ou arns"] = &ec2.ModifyImageAttributeInput{ OrganizationalUnitArns: ouArns, - LaunchPermission: &ec2.LaunchPermissionModifications{ + LaunchPermission: &ec2types.LaunchPermissionModifications{ Add: addsImage, }, } } if len(s.ProductCodes) > 0 { - codes := make([]*string, len(s.ProductCodes)) + codes := make([]string, len(s.ProductCodes)) for i, c := range s.ProductCodes { - codes[i] = &c + codes[i] = c } options["product codes"] = &ec2.ModifyImageAttributeInput{ ProductCodes: codes, @@ -198,8 +194,8 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State if s.IMDSSupport != "" { options["imds_support"] = &ec2.ModifyImageAttributeInput{ - ImdsSupport: &ec2.AttributeValue{ - Value: &s.IMDSSupport, + ImdsSupport: &ec2types.AttributeValue{ + Value: aws.String(string(s.IMDSSupport)), }, } } @@ -207,13 +203,13 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State // Modifying image attributes for region, ami := range amis { ui.Say(fmt.Sprintf("Modifying attributes on AMI (%s)...", ami)) - regionConn := ec2.New(session, &aws.Config{ - Region: aws.String(region), + regionConn := ec2.NewFromConfig(awscfg.Copy(), func(o *ec2.Options) { + o.Region = region }) for name, input := range options { - ui.Message(fmt.Sprintf("Modifying: %s", name)) + ui.Sayf("Modifying: %s", name) input.ImageId = &ami - _, err := regionConn.ModifyImageAttribute(input) + _, err := regionConn.ModifyImageAttribute(ctx, input) if err != nil { err := fmt.Errorf("Error modify AMI attributes: %s", err) state.Put("error", err) @@ -227,13 +223,13 @@ func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.State for region, region_snapshots := range snapshots { for _, snapshot := range region_snapshots { ui.Say(fmt.Sprintf("Modifying attributes on snapshot (%s)...", snapshot)) - regionConn := ec2.New(session, &aws.Config{ - Region: aws.String(region), + regionConn := ec2.NewFromConfig(awscfg.Copy(), func(o *ec2.Options) { + o.Region = region }) for name, input := range snapshotOptions { - ui.Message(fmt.Sprintf("Modifying: %s", name)) + ui.Sayf("Modifying: %s", name) input.SnapshotId = &snapshot - _, err := regionConn.ModifySnapshotAttribute(input) + _, err := regionConn.ModifySnapshotAttribute(ctx, input) if err != nil { err := fmt.Errorf("Error modify snapshot attributes: %s", err) state.Put("error", err) diff --git a/builder/common/step_modify_ebs_instance.go b/builder/common/step_modify_ebs_instance.go index b05e6c17..453134e6 100644 --- a/builder/common/step_modify_ebs_instance.go +++ b/builder/common/step_modify_ebs_instance.go @@ -8,7 +8,8 @@ import ( "fmt" "strings" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -23,7 +24,7 @@ type StepModifyEBSBackedInstance struct { func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ec2conn := state.Get("ec2").(clients.Ec2Client) - instance := state.Get("instance").(*ec2.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) // Skip when it is a spot instance @@ -36,9 +37,9 @@ func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.S if s.EnableAMISriovNetSupport { ui.Say("Enabling Enhanced Networking (SR-IOV)...") simple := "simple" - _, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{ + _, err := ec2conn.ModifyInstanceAttribute(ctx, &ec2.ModifyInstanceAttributeInput{ InstanceId: instance.InstanceId, - SriovNetSupport: &ec2.AttributeValue{Value: &simple}, + SriovNetSupport: &ec2types.AttributeValue{Value: &simple}, }) if err != nil { err := fmt.Errorf("Error enabling Enhanced Networking (SR-IOV) on %s: %s", *instance.InstanceId, err) @@ -58,9 +59,9 @@ func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.S prefix = "Dis" } ui.Say(fmt.Sprintf("%sabling Enhanced Networking (ENA)...", prefix)) - _, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{ + _, err := ec2conn.ModifyInstanceAttribute(ctx, &ec2.ModifyInstanceAttributeInput{ InstanceId: instance.InstanceId, - EnaSupport: &ec2.AttributeBooleanValue{Value: s.EnableAMIENASupport.ToBoolPointer()}, + EnaSupport: &ec2types.AttributeBooleanValue{Value: s.EnableAMIENASupport.ToBoolPointer()}, }) if err != nil { err := fmt.Errorf("Error %sabling Enhanced Networking (ENA) on %s: %s", strings.ToLower(prefix), *instance.InstanceId, err) diff --git a/builder/common/step_network_info_test.go b/builder/common/step_network_info_test.go index b25ba86a..c365ac8f 100644 --- a/builder/common/step_network_info_test.go +++ b/builder/common/step_network_info_test.go @@ -9,8 +9,9 @@ import ( "strings" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/google/go-cmp/cmp" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" @@ -21,30 +22,30 @@ import ( type mockEC2ClientStepNetworkTests struct { clients.Ec2Client - describeInstanceTypeOfferings func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) - describeVpcs func(*ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) - describeSubnets func(*ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) + describeInstanceTypeOfferings func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) + describeVpcs func(ctx context.Context, in *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) + describeSubnets func(ctx context.Context, in *ec2.DescribeSubnetsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeSubnetsOutput, error) } -func (m *mockEC2ClientStepNetworkTests) DescribeInstanceTypeOfferings(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { +func (m *mockEC2ClientStepNetworkTests) DescribeInstanceTypeOfferings(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { if m.describeInstanceTypeOfferings != nil { - return m.describeInstanceTypeOfferings(in) + return m.describeInstanceTypeOfferings(ctx, in, optFns...) } return nil, fmt.Errorf("unimplemented: describeInstanceTypeOfferings") } -func (m *mockEC2ClientStepNetworkTests) DescribeVpcs(in *ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) { +func (m *mockEC2ClientStepNetworkTests) DescribeVpcs(ctx context.Context, in *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) { if m.describeVpcs != nil { - return m.describeVpcs(in) + return m.describeVpcs(ctx, in, optFns...) } return nil, fmt.Errorf("unimplemented: describeVpcs") } -func (m *mockEC2ClientStepNetworkTests) DescribeSubnets(in *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) { +func (m *mockEC2ClientStepNetworkTests) DescribeSubnets(ctx context.Context, in *ec2.DescribeSubnetsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeSubnetsOutput, error) { if m.describeSubnets != nil { - return m.describeSubnets(in) + return m.describeSubnets(ctx, in, optFns...) } return nil, fmt.Errorf("unimplemented: describeSubnets") @@ -53,15 +54,15 @@ func (m *mockEC2ClientStepNetworkTests) DescribeSubnets(in *ec2.DescribeSubnetsI func TestStepNetwork_GetFilterAZByMachineType(t *testing.T) { testcases := []struct { name string - describeImpl func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) - machineType string + describeImpl func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) + machineType ec2types.InstanceType inputAZs []string expectedAZs []string expectError bool }{ { name: "Fail: describe returns an error", - describeImpl: func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { + describeImpl: func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { return nil, fmt.Errorf("STOP") }, machineType: "t2.micro", @@ -71,14 +72,14 @@ func TestStepNetwork_GetFilterAZByMachineType(t *testing.T) { }, { name: "Fail, no AZ match machine type", - describeImpl: func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { + describeImpl: func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { return &ec2.DescribeInstanceTypeOfferingsOutput{ - InstanceTypeOfferings: []*ec2.InstanceTypeOffering{ + InstanceTypeOfferings: []ec2types.InstanceTypeOffering{ { - InstanceType: aws.String("t3.mini"), + InstanceType: "t3.mini", }, { - InstanceType: aws.String("t2.mini"), + InstanceType: "t2.mini", }, }, }, nil @@ -90,11 +91,11 @@ func TestStepNetwork_GetFilterAZByMachineType(t *testing.T) { }, { name: "OK, found at least one AZ matching machine type", - describeImpl: func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { + describeImpl: func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { return &ec2.DescribeInstanceTypeOfferingsOutput{ - InstanceTypeOfferings: []*ec2.InstanceTypeOffering{ + InstanceTypeOfferings: []ec2types.InstanceTypeOffering{ { - InstanceType: aws.String("t2.micro"), + InstanceType: "t2.micro", }, }, }, nil @@ -111,7 +112,7 @@ func TestStepNetwork_GetFilterAZByMachineType(t *testing.T) { conn := &mockEC2ClientStepNetworkTests{} conn.describeInstanceTypeOfferings = tt.describeImpl - retAZ, err := filterAZByMachineType(tt.inputAZs, tt.machineType, conn) + retAZ, err := filterAZByMachineType(t.Context(), tt.inputAZs, tt.machineType, conn) diff := cmp.Diff(retAZ, tt.expectedAZs) if diff != "" { @@ -132,13 +133,13 @@ func TestStepNetwork_GetFilterAZByMachineType(t *testing.T) { func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { testcases := []struct { name string - inSubnets []*ec2.Subnet + inSubnets []ec2types.Subnet azs []string - outSubnets []*ec2.Subnet + outSubnets []ec2types.Subnet }{ { name: "No subnet matching", - inSubnets: []*ec2.Subnet{ + inSubnets: []ec2types.Subnet{ { AvailabilityZone: aws.String("us-east-1-c"), }, @@ -148,7 +149,7 @@ func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { }, { name: "Found subnet matching", - inSubnets: []*ec2.Subnet{ + inSubnets: []ec2types.Subnet{ { SubnetId: aws.String("subnet1"), AvailabilityZone: aws.String("us-east-1c"), @@ -159,7 +160,7 @@ func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { }, }, azs: []string{"us-east-1c"}, - outSubnets: []*ec2.Subnet{ + outSubnets: []ec2types.Subnet{ { SubnetId: aws.String("subnet1"), AvailabilityZone: aws.String("us-east-1c"), @@ -168,7 +169,7 @@ func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { }, { name: "Found multiple subnets matching", - inSubnets: []*ec2.Subnet{ + inSubnets: []ec2types.Subnet{ { SubnetId: aws.String("subnet1"), AvailabilityZone: aws.String("us-east-1c"), @@ -179,7 +180,7 @@ func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { }, }, azs: []string{"us-east-1c"}, - outSubnets: []*ec2.Subnet{ + outSubnets: []ec2types.Subnet{ { SubnetId: aws.String("subnet1"), AvailabilityZone: aws.String("us-east-1c"), @@ -205,7 +206,7 @@ func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { func TestStepNetwork_WithPublicIPSetAndNoVPCOrSubnet(t *testing.T) { mockConn := &mockEC2ClientStepNetworkTests{ - describeVpcs: func(dvi *ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) { + describeVpcs: func(ctx context.Context, dvi *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) { ok := false for _, filter := range dvi.Filters { if *filter.Name == "is-default" { @@ -219,22 +220,22 @@ func TestStepNetwork_WithPublicIPSetAndNoVPCOrSubnet(t *testing.T) { } return &ec2.DescribeVpcsOutput{ - Vpcs: []*ec2.Vpc{ + Vpcs: []ec2types.Vpc{ { VpcId: aws.String("default-vpc"), }, }, }, nil }, - describeSubnets: func(dsi *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) { + describeSubnets: func(ctx context.Context, dsi *ec2.DescribeSubnetsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeSubnetsOutput, error) { if dsi.SubnetIds != nil { sub := dsi.SubnetIds[0] - if *sub != "subnet1" { - return nil, fmt.Errorf("expected selected subnet to be us-east-1a, but was %q", *sub) + if sub != "subnet1" { + return nil, fmt.Errorf("expected selected subnet to be us-east-1a, but was %s", sub) } return &ec2.DescribeSubnetsOutput{ - Subnets: []*ec2.Subnet{ + Subnets: []ec2types.Subnet{ { SubnetId: aws.String("subnet1"), AvailabilityZone: aws.String("us-east-1a"), @@ -249,7 +250,7 @@ func TestStepNetwork_WithPublicIPSetAndNoVPCOrSubnet(t *testing.T) { if *filter.Name != "vpc-id" { continue } - filterVal := *filter.Values[0] + filterVal := filter.Values[0] if filterVal != "default-vpc" { return nil, fmt.Errorf("expected vpc-id filter to be %q, got %q", "default-vpc", filterVal) } @@ -262,26 +263,26 @@ func TestStepNetwork_WithPublicIPSetAndNoVPCOrSubnet(t *testing.T) { } return &ec2.DescribeSubnetsOutput{ - Subnets: []*ec2.Subnet{ + Subnets: []ec2types.Subnet{ { AvailabilityZone: aws.String("us-east-1a"), SubnetId: aws.String("subnet1"), - AvailableIpAddressCount: aws.Int64(256), + AvailableIpAddressCount: aws.Int32(256), }, { AvailabilityZone: aws.String("us-east-1b"), SubnetId: aws.String("subnet2"), - AvailableIpAddressCount: aws.Int64(512), + AvailableIpAddressCount: aws.Int32(512), }, }, }, nil }, - describeInstanceTypeOfferings: func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { - if *in.LocationType != "availability-zone" { - return nil, fmt.Errorf("called DescribeInstanceTypeOfferings with LocationType = %q, expected availability_zone", *in.LocationType) + describeInstanceTypeOfferings: func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { + if in.LocationType != ec2types.LocationTypeAvailabilityZone { + return nil, fmt.Errorf("called DescribeInstanceTypeOfferings with LocationType = %q, expected availability_zone", in.LocationType) } - var machines []*ec2.InstanceTypeOffering + var machines []ec2types.InstanceTypeOffering foundLocation := false for _, filter := range in.Filters { @@ -290,24 +291,24 @@ func TestStepNetwork_WithPublicIPSetAndNoVPCOrSubnet(t *testing.T) { } foundLocation = true - filterVal := *filter.Values[0] + filterVal := filter.Values[0] switch filterVal { case "us-east-1a": - machines = []*ec2.InstanceTypeOffering{ + machines = []ec2types.InstanceTypeOffering{ { - InstanceType: aws.String("t2.mini"), + InstanceType: "t2.mini", }, { - InstanceType: aws.String("t3.large"), + InstanceType: "t3.large", }, } case "us-east-1b": - machines = []*ec2.InstanceTypeOffering{ + machines = []ec2types.InstanceTypeOffering{ { - InstanceType: aws.String("t2.mini"), + InstanceType: "t2.mini", }, { - InstanceType: aws.String("t2.micro"), + InstanceType: "t2.micro", }, } default: @@ -360,7 +361,7 @@ func TestStepNetwork_WithPublicIPSetAndNoVPCOrSubnet(t *testing.T) { func TestStepNetwork_GetDefaultVPCFailDueToPermissions(t *testing.T) { mockConn := &mockEC2ClientStepNetworkTests{ - describeVpcs: func(dvi *ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) { + describeVpcs: func(ctx context.Context, dvi *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) { return nil, fmt.Errorf("Insufficient permissions: missing ec2:DescribeVpcs") }, } @@ -461,7 +462,7 @@ func TestStepNetwork_SetVPCAndSubnetWithoutAssociatePublicIP(t *testing.T) { func TestStepNetwork_SetPublicIPAddressWithoutSubnetAndMissingDescribeInstanceTypeOfferings(t *testing.T) { mockConn := &mockEC2ClientStepNetworkTests{ - describeVpcs: func(dvi *ec2.DescribeVpcsInput) (*ec2.DescribeVpcsOutput, error) { + describeVpcs: func(ctx context.Context, dvi *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) { ok := false for _, filter := range dvi.Filters { if *filter.Name == "is-default" { @@ -475,22 +476,22 @@ func TestStepNetwork_SetPublicIPAddressWithoutSubnetAndMissingDescribeInstanceTy } return &ec2.DescribeVpcsOutput{ - Vpcs: []*ec2.Vpc{ + Vpcs: []ec2types.Vpc{ { VpcId: aws.String("default-vpc"), }, }, }, nil }, - describeSubnets: func(dsi *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) { + describeSubnets: func(ctx context.Context, dsi *ec2.DescribeSubnetsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeSubnetsOutput, error) { if dsi.SubnetIds != nil { sub := dsi.SubnetIds[0] - if *sub != "subnet1" { - return nil, fmt.Errorf("expected selected subnet to be us-east-1a, but was %q", *sub) + if sub != "subnet1" { + return nil, fmt.Errorf("expected selected subnet to be us-east-1a, but was %q", sub) } return &ec2.DescribeSubnetsOutput{ - Subnets: []*ec2.Subnet{ + Subnets: []ec2types.Subnet{ { SubnetId: aws.String("subnet1"), AvailabilityZone: aws.String("us-east-1a"), @@ -505,7 +506,7 @@ func TestStepNetwork_SetPublicIPAddressWithoutSubnetAndMissingDescribeInstanceTy if *filter.Name != "vpc-id" { continue } - filterVal := *filter.Values[0] + filterVal := filter.Values[0] if filterVal != "default-vpc" { return nil, fmt.Errorf("expected vpc-id filter to be %q, got %q", "default-vpc", filterVal) } @@ -518,21 +519,21 @@ func TestStepNetwork_SetPublicIPAddressWithoutSubnetAndMissingDescribeInstanceTy } return &ec2.DescribeSubnetsOutput{ - Subnets: []*ec2.Subnet{ + Subnets: []ec2types.Subnet{ { AvailabilityZone: aws.String("us-east-1a"), SubnetId: aws.String("subnet1"), - AvailableIpAddressCount: aws.Int64(256), + AvailableIpAddressCount: aws.Int32(256), }, { AvailabilityZone: aws.String("us-east-1b"), SubnetId: aws.String("subnet2"), - AvailableIpAddressCount: aws.Int64(512), + AvailableIpAddressCount: aws.Int32(512), }, }, }, nil }, - describeInstanceTypeOfferings: func(in *ec2.DescribeInstanceTypeOfferingsInput) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { + describeInstanceTypeOfferings: func(ctx context.Context, in *ec2.DescribeInstanceTypeOfferingsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstanceTypeOfferingsOutput, error) { return nil, fmt.Errorf("Missing permission: ec2:DescribeInstanceTypeOfferings") }, } diff --git a/builder/common/step_pre_validate.go b/builder/common/step_pre_validate.go index 3086b443..49a58993 100644 --- a/builder/common/step_pre_validate.go +++ b/builder/common/step_pre_validate.go @@ -9,8 +9,9 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" @@ -52,11 +53,11 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - ec2conn, err := accessconf.NewEC2Connection() + ec2conn, err := accessconf.NewEC2Connection(ctx) if err != nil { return err } - _, err = listEC2Regions(ec2conn) + _, err = listEC2Regions(ctx, ec2conn) return err }) @@ -71,7 +72,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul amiconf := amiConfig.(*AMIConfig) if !amiconf.AMISkipRegionValidation { regionsToValidate := append(amiconf.AMIRegions, accessconf.RawRegion) - err := accessconf.ValidateRegion(regionsToValidate...) + err := accessconf.ValidateRegion(ctx, regionsToValidate...) if err != nil { state.Put("error", fmt.Errorf("error validating regions: %v", err)) return multistep.ActionHalt @@ -95,26 +96,27 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul return multistep.ActionContinue } - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) // Validate VPC settings for non-default VPCs ui.Say("Prevalidating any provided VPC information") - if err := s.checkVpc(ec2conn); err != nil { + if err := s.checkVpc(ctx, ec2conn); err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } ui.Say(fmt.Sprintf("Prevalidating AMI Name: %s", s.DestAmiName)) - req, resp := ec2conn.DescribeImagesRequest(&ec2.DescribeImagesInput{ - Owners: []*string{aws.String("self")}, - Filters: []*ec2.Filter{{ + resp, err := ec2conn.DescribeImages(ctx, &ec2.DescribeImagesInput{ + Owners: []string{"self"}, + Filters: []ec2types.Filter{{ Name: aws.String("name"), - Values: []*string{aws.String(s.DestAmiName)}, - }}}) - req.RetryCount = 11 + Values: []string{s.DestAmiName}, + }}}, func(o *ec2.Options) { + o.RetryMaxAttempts = 11 + }) - if err := req.Send(); err != nil { + if err != nil { err = fmt.Errorf("Error querying AMI: %s", err) state.Put("error", err) ui.Error(err.Error()) @@ -131,7 +133,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul return multistep.ActionContinue } -func (s *StepPreValidate) checkVpc(conn clients.Ec2Client) error { +func (s *StepPreValidate) checkVpc(ctx context.Context, conn clients.Ec2Client) error { if s.VpcId == "" || (s.VpcId != "" && (s.SubnetId != "" || s.HasSubnetFilter)) { // Skip validation if: // * The user has not provided a VpcId. @@ -140,13 +142,13 @@ func (s *StepPreValidate) checkVpc(conn clients.Ec2Client) error { return nil } - res, err := conn.DescribeVpcs(&ec2.DescribeVpcsInput{VpcIds: []*string{aws.String(s.VpcId)}}) + res, err := conn.DescribeVpcs(ctx, &ec2.DescribeVpcsInput{VpcIds: []string{s.VpcId}}) if awserrors.Matches(err, "InvalidVpcID.NotFound", "") || err != nil { return fmt.Errorf("Error retrieving VPC information for vpc_id %s: %s", s.VpcId, err) } - if res != nil && len(res.Vpcs) == 1 && res.Vpcs[0] != nil { - if isDefault := aws.BoolValue(res.Vpcs[0].IsDefault); !isDefault { + if res != nil && len(res.Vpcs) == 1 { + if isDefault := aws.ToBool(res.Vpcs[0].IsDefault); !isDefault { return fmt.Errorf("Error: subnet_id or subnet_filter must be provided for non-default VPCs (%s)", s.VpcId) } } diff --git a/builder/common/step_pre_validate_test.go b/builder/common/step_pre_validate_test.go index 4d797d60..1c8d7813 100644 --- a/builder/common/step_pre_validate_test.go +++ b/builder/common/step_pre_validate_test.go @@ -53,14 +53,14 @@ func TestStepPreValidate_checkVpc(t *testing.T) { {"NonDefaultVpcWithSubnetFilter", StepPreValidate{VpcId: "vpc-1234567890", HasSubnetFilter: true}, false}, } - mockConn, err := getMockConn(nil, "") + mockConn, err := getMockConn(t.Context(), FakeAccessConfig(), "") if err != nil { t.Fatal("unable to get a mock connection") } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - err := tc.step.checkVpc(mockConn) + err := tc.step.checkVpc(t.Context(), mockConn) if tc.errorExpected && err == nil { t.Errorf("expected a validation error for %q but got %q", tc.name, err) diff --git a/builder/common/step_run_spot_instance.go b/builder/common/step_run_spot_instance.go index 4aff6ba8..a72e8477 100644 --- a/builder/common/step_run_spot_instance.go +++ b/builder/common/step_run_spot_instance.go @@ -52,7 +52,7 @@ type StepRunSpotInstance struct { SpotAllocationStrategy ec2types.SpotAllocationStrategy SpotPrice string SpotTags map[string]string - SpotInstanceTypes []ec2types.InstanceType + SpotInstanceTypes []string Tags map[string]string VolumeTags map[string]string UserData string @@ -363,7 +363,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) var overrides []ec2types.FleetLaunchTemplateOverridesRequest for _, instanceType := range s.SpotInstanceTypes { override := ec2types.FleetLaunchTemplateOverridesRequest{ - InstanceType: instanceType, + InstanceType: ec2types.InstanceType(instanceType), } overrides = append(overrides, override) } diff --git a/builder/common/step_security_group.go b/builder/common/step_security_group.go index 2ace1db1..40434043 100644 --- a/builder/common/step_security_group.go +++ b/builder/common/step_security_group.go @@ -11,9 +11,10 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -36,15 +37,15 @@ type StepSecurityGroup struct { } func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) vpcId := state.Get("vpc_id").(string) + awscfg := state.Get("awsConfig").(*aws.Config) if len(s.SecurityGroupIds) > 0 { - _, err := ec2conn.DescribeSecurityGroups( - &ec2.DescribeSecurityGroupsInput{ - GroupIds: aws.StringSlice(s.SecurityGroupIds), - }, + _, err := ec2conn.DescribeSecurityGroups(ctx, &ec2.DescribeSecurityGroupsInput{ + GroupIds: s.SecurityGroupIds, + }, ) if err != nil { err := fmt.Errorf("Couldn't find specified security group: %s", err) @@ -74,7 +75,7 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m log.Printf("Using SecurityGroup Filters %v", params) - sgResp, err := ec2conn.DescribeSecurityGroups(params) + sgResp, err := ec2conn.DescribeSecurityGroups(ctx, params) if err != nil { err := fmt.Errorf("Couldn't find security groups for filter: %s", err) log.Printf("[DEBUG] %s", err.Error()) @@ -102,7 +103,7 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m } if !s.IsRestricted { - ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, awscfg.Region, state) if err != nil { err := fmt.Errorf("Error tagging security group: %s", err) state.Put("error", err) @@ -110,12 +111,12 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m return multistep.ActionHalt } - group.TagSpecifications = ec2Tags.TagSpecifications(ec2.ResourceTypeSecurityGroup) + group.TagSpecifications = ec2Tags.TagSpecifications(ec2types.ResourceTypeSecurityGroup) } group.VpcId = &vpcId - groupResp, err := ec2conn.CreateSecurityGroup(group) + groupResp, err := ec2conn.CreateSecurityGroup(ctx, group) if err != nil { ui.Error(err.Error()) state.Put("error", err) @@ -127,11 +128,8 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m // Wait for the security group become available for authorizing log.Printf("[DEBUG] Waiting for temporary security group: %s", s.createdGroupId) - err = waitUntilSecurityGroupExists(ec2conn, - &ec2.DescribeSecurityGroupsInput{ - GroupIds: []*string{aws.String(s.createdGroupId)}, - }, - ) + w := ec2.NewSecurityGroupExistsWaiter(ec2conn) + err = w.Wait(ctx, &ec2.DescribeSecurityGroupsInput{GroupIds: []string{s.createdGroupId}}, 200*time.Second) if err != nil { err := fmt.Errorf("Timed out waiting for security group %s: %s", s.createdGroupId, err) log.Printf("[DEBUG] %s", err.Error()) @@ -178,8 +176,8 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m // map the list of temporary security group CIDRs bundled with config to // types expected by EC2. - groupIpRanges := []*ec2.IpRange{} - groupIpv6Ranges := []*ec2.Ipv6Range{} + groupIpRanges := []ec2types.IpRange{} + groupIpv6Ranges := []ec2types.Ipv6Range{} for _, cidr := range temporarySGSourceCidrs { _, ipNet, err := net.ParseCIDR(cidr) if err != nil { @@ -189,12 +187,12 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m } if ipNet.IP.To4() != nil { // IPv4 CIDR - groupIpRanges = append(groupIpRanges, &ec2.IpRange{ + groupIpRanges = append(groupIpRanges, ec2types.IpRange{ CidrIp: aws.String(cidr), }) } else { // IPv6 CIDR - groupIpv6Ranges = append(groupIpv6Ranges, &ec2.Ipv6Range{ + groupIpv6Ranges = append(groupIpv6Ranges, ec2types.Ipv6Range{ CidrIpv6: aws.String(cidr), }) } @@ -212,10 +210,10 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m // Authorize access for the provided port within the security group groupRules := &ec2.AuthorizeSecurityGroupIngressInput{ GroupId: groupResp.GroupId, - IpPermissions: []*ec2.IpPermission{ + IpPermissions: []ec2types.IpPermission{ { - FromPort: aws.Int64(int64(port)), - ToPort: aws.Int64(int64(port)), + FromPort: aws.Int32(int32(port)), + ToPort: aws.Int32(int32(port)), Ipv6Ranges: groupIpv6Ranges, IpRanges: groupIpRanges, IpProtocol: aws.String("tcp"), @@ -227,7 +225,7 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m "Authorizing access to port %d from %v in the temporary security groups...", port, temporarySGSourceCidrs), ) - _, err = ec2conn.AuthorizeSecurityGroupIngress(groupRules) + _, err = ec2conn.AuthorizeSecurityGroupIngress(ctx, groupRules) if err != nil { err := fmt.Errorf("Error authorizing temporary security group: %s", err) state.Put("error", err) @@ -243,14 +241,15 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) { return } - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) + ctx := state.Get("ctx").(context.Context) ui.Say("Deleting temporary security group...") var err error for i := 0; i < 5; i++ { - _, err = ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{GroupId: &s.createdGroupId}) + _, err = ec2conn.DeleteSecurityGroup(ctx, &ec2.DeleteSecurityGroupInput{GroupId: &s.createdGroupId}) if err == nil { break } @@ -265,45 +264,3 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) { " err: %s; security group ID: %s", err, s.createdGroupId)) } } - -func waitUntilSecurityGroupExists(c *ec2.EC2, input *ec2.DescribeSecurityGroupsInput) error { - ctx := aws.BackgroundContext() - w := request.Waiter{ - Name: "DescribeSecurityGroups", - MaxAttempts: 40, - Delay: request.ConstantWaiterDelay(5 * time.Second), - Acceptors: []request.WaiterAcceptor{ - { - State: request.SuccessWaiterState, - Matcher: request.PathWaiterMatch, - Argument: "length(SecurityGroups[]) > `0`", - Expected: true, - }, - { - State: request.RetryWaiterState, - Matcher: request.ErrorWaiterMatch, - Argument: "", - Expected: "InvalidGroup.NotFound", - }, - { - State: request.RetryWaiterState, - Matcher: request.ErrorWaiterMatch, - Argument: "", - Expected: "InvalidSecurityGroupID.NotFound", - }, - }, - Logger: c.Config.Logger, - NewRequest: func(opts []request.Option) (*request.Request, error) { - var inCpy *ec2.DescribeSecurityGroupsInput - if input != nil { - tmp := *input - inCpy = &tmp - } - req, _ := c.DescribeSecurityGroupsRequest(inCpy) - req.SetContext(ctx) - req.ApplyOptions(opts...) - return req, nil - }, - } - return w.WaitWithContext(ctx) -} diff --git a/builder/common/step_source_ami_info_test.go b/builder/common/step_source_ami_info_test.go index e1620032..9a53e2a3 100644 --- a/builder/common/step_source_ami_info_test.go +++ b/builder/common/step_source_ami_info_test.go @@ -6,21 +6,20 @@ package common import ( "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/stretchr/testify/assert" ) func TestStepSourceAmiInfo_PVImage(t *testing.T) { - err := new(StepSourceAMIInfo).canEnableEnhancedNetworking(&ec2.Image{ - VirtualizationType: aws.String("paravirtual"), + err := new(StepSourceAMIInfo).canEnableEnhancedNetworking(&ec2types.Image{ + VirtualizationType: ec2types.VirtualizationTypeParavirtual, }) assert.Error(t, err) } func TestStepSourceAmiInfo_HVMImage(t *testing.T) { - err := new(StepSourceAMIInfo).canEnableEnhancedNetworking(&ec2.Image{ - VirtualizationType: aws.String("hvm"), + err := new(StepSourceAMIInfo).canEnableEnhancedNetworking(&ec2types.Image{ + VirtualizationType: ec2types.VirtualizationTypeHvm, }) assert.NoError(t, err) } @@ -29,8 +28,8 @@ func TestStepSourceAmiInfo_PVImageWithAMIVirtPV(t *testing.T) { stepSourceAMIInfo := StepSourceAMIInfo{ AMIVirtType: "paravirtual", } - err := stepSourceAMIInfo.canEnableEnhancedNetworking(&ec2.Image{ - VirtualizationType: aws.String("paravirtual"), + err := stepSourceAMIInfo.canEnableEnhancedNetworking(&ec2types.Image{ + VirtualizationType: ec2types.VirtualizationTypeParavirtual, }) assert.Error(t, err) } @@ -39,8 +38,8 @@ func TestStepSourceAmiInfo_PVImageWithAMIVirtHVM(t *testing.T) { stepSourceAMIInfo := StepSourceAMIInfo{ AMIVirtType: "hvm", } - err := stepSourceAMIInfo.canEnableEnhancedNetworking(&ec2.Image{ - VirtualizationType: aws.String("paravirtual"), + err := stepSourceAMIInfo.canEnableEnhancedNetworking(&ec2types.Image{ + VirtualizationType: ec2types.VirtualizationTypeParavirtual, }) assert.NoError(t, err) } diff --git a/builder/common/tags.go b/builder/common/tags.go index 0427080c..aaa63b70 100644 --- a/builder/common/tags.go +++ b/builder/common/tags.go @@ -69,12 +69,12 @@ func (t TagMap) IamTags(ictx interpolate.Context, region string, state multistep return iamTags, nil } -func (t EC2Tags) TagSpecifications(resourceType ...string) []*ec2types.TagSpecification { - var tagSpecs []*ec2types.TagSpecification +func (t EC2Tags) TagSpecifications(resourceType ...ec2types.ResourceType) []ec2types.TagSpecification { + var tagSpecs []ec2types.TagSpecification if len(t) > 0 { for _, resource := range resourceType { - runTags := &ec2types.TagSpecification{ - ResourceType: ec2types.ResourceType(resource), + runTags := ec2types.TagSpecification{ + ResourceType: resource, Tags: t, } tagSpecs = append(tagSpecs, runTags) diff --git a/builder/instance/builder.hcl2spec.go b/builder/instance/builder.hcl2spec.go index 68167815..0fd3caa4 100644 --- a/builder/instance/builder.hcl2spec.go +++ b/builder/instance/builder.hcl2spec.go @@ -3,6 +3,7 @@ package instance import ( + "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer-plugin-amazon/builder/common" "github.com/hashicorp/packer-plugin-sdk/template/config" @@ -38,7 +39,7 @@ type FlatConfig struct { 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"` + AMIVirtType *types.VirtualizationType `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"` AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users" hcl:"ami_users"` AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups" hcl:"ami_groups"` AMIOrgArns []string `mapstructure:"ami_org_arns" required:"false" cty:"ami_org_arns" hcl:"ami_org_arns"` @@ -57,7 +58,7 @@ type FlatConfig struct { AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids" hcl:"region_kms_key_ids"` AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region" hcl:"skip_save_build_region"` AMISnapshotCopyDurationMinutes *int64 `mapstructure:"snapshot_copy_duration_minutes" required:"false" cty:"snapshot_copy_duration_minutes" hcl:"snapshot_copy_duration_minutes"` - AMIIMDSSupport *string `mapstructure:"imds_support" required:"false" cty:"imds_support" hcl:"imds_support"` + AMIIMDSSupport *types.ImdsSupportValues `mapstructure:"imds_support" required:"false" cty:"imds_support" hcl:"imds_support"` DeprecationTime *string `mapstructure:"deprecate_at" cty:"deprecate_at" hcl:"deprecate_at"` SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"` SnapshotTag []config.FlatKeyValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag" hcl:"snapshot_tag"` @@ -66,8 +67,8 @@ type FlatConfig struct { DeregistrationProtection *common.FlatDeregistrationProtectionOptions `mapstructure:"deregistration_protection" required:"false" cty:"deregistration_protection" hcl:"deregistration_protection"` 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"` - CapacityReservationPreference *string `mapstructure:"capacity_reservation_preference" required:"false" cty:"capacity_reservation_preference" hcl:"capacity_reservation_preference"` + BlockDurationMinutes *int32 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"` + CapacityReservationPreference *types.CapacityReservationPreference `mapstructure:"capacity_reservation_preference" required:"false" cty:"capacity_reservation_preference" hcl:"capacity_reservation_preference"` CapacityReservationId *string `mapstructure:"capacity_reservation_id" required:"false" cty:"capacity_reservation_id" hcl:"capacity_reservation_id"` CapacityReservationGroupArn *string `mapstructure:"capacity_reservation_group_arn" required:"false" cty:"capacity_reservation_group_arn" hcl:"capacity_reservation_group_arn"` DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"` @@ -81,7 +82,7 @@ type FlatConfig struct { SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation" hcl:"skip_profile_validation"` TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document" hcl:"temporary_iam_instance_profile_policy_document"` InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior" hcl:"shutdown_behavior"` - InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"` + InstanceType *types.InstanceType `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"` SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter" hcl:"security_group_filter"` RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags" hcl:"run_tags"` RunTag []config.FlatKeyValue `mapstructure:"run_tag" required:"false" cty:"run_tag" hcl:"run_tag"` @@ -89,7 +90,7 @@ type FlatConfig struct { SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids" hcl:"security_group_ids"` SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"` SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"` - SpotAllocationStrategy *string `mapstructure:"spot_allocation_strategy" required:"false" cty:"spot_allocation_strategy" hcl:"spot_allocation_strategy"` + SpotAllocationStrategy *types.SpotAllocationStrategy `mapstructure:"spot_allocation_strategy" required:"false" cty:"spot_allocation_strategy" hcl:"spot_allocation_strategy"` SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types" hcl:"spot_instance_types"` SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price" hcl:"spot_price"` SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" undocumented:"true" cty:"spot_price_auto_product" hcl:"spot_price_auto_product"` @@ -99,7 +100,7 @@ type FlatConfig struct { SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"` LicenseSpecifications []common.FlatLicenseSpecification `mapstructure:"license_specifications" required:"false" cty:"license_specifications" hcl:"license_specifications"` Placement *common.FlatPlacement `mapstructure:"placement" required:"false" cty:"placement" hcl:"placement"` - Tenancy *string `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"` + Tenancy *types.Tenancy `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"` TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"` TemporarySGSourcePublicIp *bool `mapstructure:"temporary_security_group_source_public_ip" required:"false" cty:"temporary_security_group_source_public_ip" hcl:"temporary_security_group_source_public_ip"` UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"` @@ -171,7 +172,7 @@ type FlatConfig struct { X509CertPath *string `mapstructure:"x509_cert_path" required:"true" cty:"x509_cert_path" hcl:"x509_cert_path"` X509KeyPath *string `mapstructure:"x509_key_path" required:"true" cty:"x509_key_path" hcl:"x509_key_path"` X509UploadPath *string `mapstructure:"x509_upload_path" required:"false" cty:"x509_upload_path" hcl:"x509_upload_path"` - TpmSupport *string `mapstructure:"tpm_support" required:"false" cty:"tpm_support" hcl:"tpm_support"` + TpmSupport *types.TpmSupportValues `mapstructure:"tpm_support" required:"false" cty:"tpm_support" hcl:"tpm_support"` } // FlatMapstructure returns a new FlatConfig. diff --git a/docs-partials/builder/chroot/Config-not-required.mdx b/docs-partials/builder/chroot/Config-not-required.mdx index 1e2d9b55..72da9373 100644 --- a/docs-partials/builder/chroot/Config-not-required.mdx +++ b/docs-partials/builder/chroot/Config-not-required.mdx @@ -71,11 +71,11 @@ - `root_device_name` (string) - The root device name. For example, xvda. -- `root_volume_size` (int64) - The size of the root volume in GB for the chroot environment and the +- `root_volume_size` (int32) - The size of the root volume in GB for the chroot environment and the resulting AMI. Default size is the snapshot size of the source_ami unless from_scratch is true, in which case this field must be defined. -- `root_volume_type` (string) - The type of EBS volume for the chroot environment and resulting AMI. The +- `root_volume_type` (ec2types.VolumeType) - The type of EBS volume for the chroot environment and resulting AMI. The default value is the type of the source_ami, unless from_scratch is true, in which case the default value is gp2. You can only specify io1 if building based on top of a source_ami which is also io1. @@ -151,10 +151,10 @@ This field is validated by Packer, when using an alias, you will have to prefix `kms_key_id` with `alias/`. -- `ami_architecture` (string) - what architecture to use when registering the final AMI; valid options +- `ami_architecture` (ec2types.ArchitectureValues) - what architecture to use when registering the final AMI; valid options are "arm64", "arm64_mac", "i386", "x86_64", or "x86_64_mac". Defaults to "x86_64". -- `boot_mode` (string) - The boot mode. Valid options are `legacy-bios` and `uefi`. See the documentation on +- `boot_mode` (ec2types.BootModeValues) - The boot mode. Valid options are `legacy-bios` and `uefi`. See the documentation on [boot modes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ami-boot.html) for more information. Defaults to `legacy-bios` when `ami_architecture` is `x86_64` and `uefi` when `ami_architecture` is `arm64`. @@ -162,7 +162,7 @@ - `uefi_data` (string) - Base64 representation of the non-volatile UEFI variable store. For more information see [AWS documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/uefi-secure-boot-optionB.html). -- `tpm_support` (string) - NitroTPM Support. Valid options are `v2.0`. See the documentation on +- `tpm_support` (ec2types.TpmSupportValues) - NitroTPM Support. Valid options are `v2.0`. See the documentation on [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for more information. Only enabled if a valid option is provided, otherwise ignored. diff --git a/docs-partials/builder/common/AMIConfig-not-required.mdx b/docs-partials/builder/common/AMIConfig-not-required.mdx index 1d1d9998..b0c53961 100644 --- a/docs-partials/builder/common/AMIConfig-not-required.mdx +++ b/docs-partials/builder/common/AMIConfig-not-required.mdx @@ -5,7 +5,7 @@ [template engine](/packer/docs/templates/legacy_json_templates/engine), see [Build template data](#build-template-data) for more information. -- `ami_virtualization_type` (string) - The type of virtualization for the AMI +- `ami_virtualization_type` (ec2types.VirtualizationType) - The type of virtualization for the AMI you are building. This option is required to register HVM images. Can be paravirtual (default) or hvm. @@ -140,7 +140,7 @@ [Time-based copies]: https://docs.aws.amazon.com/ebs/latest/userguide/time-based-copies.html -- `imds_support` (string) - Enforce version of the Instance Metadata Service on the built AMI. +- `imds_support` (ec2types.ImdsSupportValues) - Enforce version of the Instance Metadata Service on the built AMI. Valid options are unset (legacy) and `v2.0`. See the documentation on [IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for more information. Defaults to legacy. diff --git a/docs-partials/builder/common/AWSPollingConfig-not-required.mdx b/docs-partials/builder/common/AWSPollingConfig-not-required.mdx index 4333f877..b16fb4bf 100644 --- a/docs-partials/builder/common/AWSPollingConfig-not-required.mdx +++ b/docs-partials/builder/common/AWSPollingConfig-not-required.mdx @@ -10,4 +10,9 @@ 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. +- `max_timeout` (int) - Specifies the maximum timeout in seconds for the waiter. + This value can also be set via the AWS_MAX_TIMEOUT. + If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + diff --git a/docs-partials/builder/common/BlockDevice-not-required.mdx b/docs-partials/builder/common/BlockDevice-not-required.mdx index 2a11a512..a8fd48d5 100644 --- a/docs-partials/builder/common/BlockDevice-not-required.mdx +++ b/docs-partials/builder/common/BlockDevice-not-required.mdx @@ -13,7 +13,7 @@ false will result in an unencrypted device, and true will result in an encrypted one. -- `iops` (\*int64) - The number of I/O operations per second (IOPS) that the volume supports. +- `iops` (\*int32) - The number of I/O operations per second (IOPS) that the volume supports. See the documentation on [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -23,7 +23,7 @@ - `snapshot_id` (string) - The ID of the snapshot. -- `throughput` (\*int64) - The throughput for gp3 volumes, only valid for gp3 types +- `throughput` (\*int32) - The throughput for gp3 volumes, only valid for gp3 types See the documentation on [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -37,11 +37,11 @@ The volume virtual_name should be in the `ephemeral[0-23]` form, e.g. ephemeral1 -- `volume_type` (string) - The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2 +- `volume_type` (ec2types.VolumeType) - The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2 for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. -- `volume_size` (int64) - The size of the volume, in GiB. Required if not specifying a +- `volume_size` (int32) - The size of the volume, in GiB. Required if not specifying a snapshot_id. - `kms_key_id` (string) - ID, alias or ARN of the KMS key to use for boot volume encryption. diff --git a/docs-partials/builder/common/Placement-not-required.mdx b/docs-partials/builder/common/Placement-not-required.mdx index b848477c..3b296dcc 100644 --- a/docs-partials/builder/common/Placement-not-required.mdx +++ b/docs-partials/builder/common/Placement-not-required.mdx @@ -4,7 +4,7 @@ - `host_id` (string) - The ID of the host used when Packer launches an EC2 instance. -- `tenancy` (string) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used +- `tenancy` (ec2types.Tenancy) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware. The default is "default", meaning shared tenancy. Allowed values are "default", diff --git a/docs-partials/builder/common/RunConfig-not-required.mdx b/docs-partials/builder/common/RunConfig-not-required.mdx index d0eadce3..af9fc605 100644 --- a/docs-partials/builder/common/RunConfig-not-required.mdx +++ b/docs-partials/builder/common/RunConfig-not-required.mdx @@ -22,7 +22,7 @@ - `availability_zone` (string) - Destination availability zone to launch instance in. Leave this empty to allow Amazon to auto-assign. -- `block_duration_minutes` (int64) - Requires spot_price to be set. The +- `block_duration_minutes` (int32) - Requires spot_price to be set. The required duration for the Spot Instances (also known as Spot blocks). This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360). You can't specify an Availability Zone group or a launch group if you specify a @@ -30,7 +30,7 @@ from July 1, 2021. [See Amazon's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances). -- `capacity_reservation_preference` (string) - Set the preference for using a capacity reservation if one exists. +- `capacity_reservation_preference` (ec2types.CapacityReservationPreference) - Set the preference for using a capacity reservation if one exists. Either will be `open` or `none`. Defaults to `none` - `capacity_reservation_id` (string) - Provide the specific EC2 Capacity Reservation ID that will be used @@ -277,7 +277,7 @@ criteria provided in `source_ami_filter`; this pins the AMI returned by the filter, but will cause Packer to fail if the `source_ami` does not exist. -- `spot_allocation_strategy` (string) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. +- `spot_allocation_strategy` (ec2types.SpotAllocationStrategy) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. The strategy that determines how to allocate the target Spot Instance capacity across the Spot Instance pools specified by the EC2 Fleet launch configuration. If this option is not set, Packer will use default option provided by the SDK (currently `lowest-price`). @@ -434,7 +434,7 @@ Refer to the [Placement docs](#placement-configuration) for more information on the supported attributes for placement configuration. -- `tenancy` (string) - Deprecated: Use Placement Tenancy instead. +- `tenancy` (ec2types.Tenancy) - Deprecated: Use Placement Tenancy instead. - `temporary_security_group_source_cidrs` ([]string) - A list of IPv4/IPv6 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. diff --git a/docs-partials/builder/common/RunConfig-required.mdx b/docs-partials/builder/common/RunConfig-required.mdx index fc014168..6c6cfdc7 100644 --- a/docs-partials/builder/common/RunConfig-required.mdx +++ b/docs-partials/builder/common/RunConfig-required.mdx @@ -1,6 +1,6 @@ -- `instance_type` (string) - The EC2 instance type to use while building the +- `instance_type` (ec2types.InstanceType) - The EC2 instance type to use while building the AMI, such as t2.small. - `source_ami` (string) - The source AMI whose root volume will be copied and diff --git a/docs-partials/builder/common/volumeAttachedDetachedWaiterOptions.mdx b/docs-partials/builder/common/volumeAttachedDetachedWaiterOptions.mdx new file mode 100644 index 00000000..512446ce --- /dev/null +++ b/docs-partials/builder/common/volumeAttachedDetachedWaiterOptions.mdx @@ -0,0 +1,5 @@ + + +Custom SDK v2 waiters that we have to implement ourselves because the AWS SDK doesn't have built-in waiters for these actions. + + diff --git a/docs-partials/builder/instance/Config-not-required.mdx b/docs-partials/builder/instance/Config-not-required.mdx index a5a89edd..d0b89415 100644 --- a/docs-partials/builder/instance/Config-not-required.mdx +++ b/docs-partials/builder/instance/Config-not-required.mdx @@ -37,7 +37,7 @@ okay to create this directory as part of the provisioning process. Defaults to /tmp. -- `tpm_support` (string) - NitroTPM Support. Valid options are `v2.0`. See the documentation on +- `tpm_support` (ec2types.TpmSupportValues) - NitroTPM Support. Valid options are `v2.0`. See the documentation on [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for more information. Only enabled if a valid option is provided, otherwise ignored. diff --git a/go.mod b/go.mod index 58899521..f811e28e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssm v1.68.6 github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 github.com/google/go-cmp v0.7.0 - github.com/hashicorp/aws-sdk-go-base v1.1.0 github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-multierror v1.1.1 diff --git a/go.sum b/go.sum index 9322faa1..1f0890ea 100644 --- a/go.sum +++ b/go.sum @@ -51,7 +51,6 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6 github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= @@ -164,7 +163,6 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= @@ -213,8 +211,6 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/hashicorp/aws-sdk-go-base v1.1.0 h1:27urM3JAp6v+Oj/Ea5ULZwuFPK9cO1RUdEpV+rNdSAc= -github.com/hashicorp/aws-sdk-go-base v1.1.0/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY= github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= github.com/hashicorp/consul/api v1.34.2 h1:B5jqSSKwWyY8U8WiGS5vmPEPkkF0bAvrECykdZkDR80= @@ -245,7 +241,6 @@ github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0= github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -300,7 +295,6 @@ github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZ github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -417,7 +411,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -479,7 +472,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= From 456798fbc918d6435d9996a90e7514e7e726e4fd Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Thu, 14 May 2026 18:40:02 +0200 Subject: [PATCH 3/8] feat: Use AWS SDK 2 only. All tests are passing --- builder/chroot/builder.go | 22 +++--- builder/chroot/builder.hcl2spec.go | 8 +- builder/chroot/step_instance_info.go | 2 +- builder/chroot/step_register_ami.go | 2 +- builder/common/access_config.go | 3 +- builder/common/block_device.go | 12 +-- builder/common/block_device.hcl2spec.go | 23 +++--- builder/common/block_device_test.go | 79 +++++++++++-------- builder/common/boot_mode_validation.go | 4 +- builder/common/boot_mode_validation_test.go | 4 +- builder/common/interpolate_build_info_test.go | 12 +-- builder/common/ssh.go | 2 +- builder/common/state.go | 58 ++++++++------ builder/common/step_ami_region_copy.go | 14 +++- builder/common/step_ami_region_copy_test.go | 9 ++- builder/common/step_cleanup_volumes.go | 30 +++---- builder/common/step_get_password.go | 13 +-- builder/common/step_network_info_test.go | 3 +- builder/common/step_run_source_instance.go | 2 +- builder/common/step_run_spot_instance.go | 2 +- builder/common/step_run_spot_instance_test.go | 17 ++-- builder/common/step_source_ami_info.go | 2 +- builder/common/step_stop_ebs_instance.go | 25 +++--- builder/common/test_helper_funcs.go | 6 +- builder/ebs/builder.go | 2 +- builder/ebs/step_create_ami.go | 4 +- builder/ebssurrogate/builder.go | 2 +- builder/ebssurrogate/step_create_ami.go | 4 +- builder/ebssurrogate/step_register_ami.go | 4 +- builder/ebssurrogate/step_snapshot_volumes.go | 4 +- builder/ebssurrogate/step_swap_volumes.go | 4 +- builder/ebsvolume/builder.go | 2 +- .../ebsvolume/step_snapshot_ebs_volumes.go | 4 +- .../step_snapshot_ebs_volumes_test.go | 4 +- builder/ebsvolume/step_tag_ebs_volumes.go | 2 +- builder/instance/step_bundle_volume.go | 6 +- common/ssh.go | 4 +- common/ssh_test.go | 2 +- common/step_ami_region_copy.go | 2 +- common/step_ami_region_copy_test.go | 2 +- common/step_cleanup_volumes.go | 2 +- common/step_create_ssm_tunnel.go | 2 +- common/step_get_password.go | 2 +- common/step_iam_instance_profile.go | 2 +- common/step_key_pair.go | 4 +- common/step_modify_ebs_instance.go | 2 +- common/step_network_info.go | 2 +- common/step_pre_validate.go | 2 +- common/step_run_source_instance.go | 6 +- common/step_run_spot_instance.go | 6 +- common/step_run_spot_instance_test.go | 30 ++++--- common/step_security_group.go | 4 +- common/step_source_ami_info.go | 14 ++-- common/step_stop_ebs_instance.go | 2 +- .../builder/chroot/Config-not-required.mdx | 8 +- .../common/BlockDevice-not-required.mdx | 2 +- 56 files changed, 271 insertions(+), 225 deletions(-) diff --git a/builder/chroot/builder.go b/builder/chroot/builder.go index 93152a92..c32792ff 100644 --- a/builder/chroot/builder.go +++ b/builder/chroot/builder.go @@ -118,7 +118,7 @@ type Config struct { // default value is the type of the source_ami, unless from_scratch is // true, in which case the default value is gp2. You can only specify io1 // if building based on top of a source_ami which is also io1. - RootVolumeType ec2types.VolumeType `mapstructure:"root_volume_type" required:"false"` + RootVolumeType string `mapstructure:"root_volume_type" required:"false"` // The source AMI whose root volume will be copied and provisioned on the // currently running instance. This must be an EBS-backed AMI with a root // volume snapshot that you have access to. Note: this is not used when @@ -197,19 +197,19 @@ type Config struct { RootVolumeKmsKeyId string `mapstructure:"root_volume_kms_key_id" required:"false"` // what architecture to use when registering the final AMI; valid options // are "arm64", "arm64_mac", "i386", "x86_64", or "x86_64_mac". Defaults to "x86_64". - Architecture ec2types.ArchitectureValues `mapstructure:"ami_architecture" required:"false"` + Architecture string `mapstructure:"ami_architecture" required:"false"` // The boot mode. Valid options are `legacy-bios` and `uefi`. See the documentation on // [boot modes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ami-boot.html) for // more information. Defaults to `legacy-bios` when `ami_architecture` is `x86_64` and // `uefi` when `ami_architecture` is `arm64`. - BootMode ec2types.BootModeValues `mapstructure:"boot_mode" required:"false"` + BootMode string `mapstructure:"boot_mode" required:"false"` // Base64 representation of the non-volatile UEFI variable store. For more information // see [AWS documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/uefi-secure-boot-optionB.html). UefiData string `mapstructure:"uefi_data" required:"false"` // NitroTPM Support. Valid options are `v2.0`. See the documentation on // [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for // more information. Only enabled if a valid option is provided, otherwise ignored. - TpmSupport ec2types.TpmSupportValues `mapstructure:"tpm_support" required:"false"` + TpmSupport string `mapstructure:"tpm_support" required:"false"` ctx interpolate.Context } @@ -371,7 +371,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { } valid := false - for _, validArch := range []ec2types.ArchitectureValues{ec2types.ArchitectureValuesArm64, ec2types.ArchitectureValuesArm64Mac, ec2types.ArchitectureValuesX8664, ec2types.ArchitectureValuesX8664Mac} { + for _, validArch := range []string{"arm64", "arm64_mac", "i386", "x86_64", "x86_64_mac"} { if validArch == b.config.Architecture { valid = true break @@ -381,7 +381,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { errs = packersdk.MultiErrorAppend(errs, errors.New(`The only valid ami_architecture values are "arm64", "arm64_mac", "i386", "x86_64", or "x86_64_mac"`)) } - if b.config.TpmSupport != "" && b.config.TpmSupport != ec2types.TpmSupportValuesV20 { + if b.config.TpmSupport != "" && b.config.TpmSupport != string(ec2types.TpmSupportValuesV20) { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`The only valid tpm_support value is %q`, ec2types.TpmSupportValuesV20)) } @@ -393,9 +393,9 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { } if b.config.UefiData != "" { - if b.config.BootMode == ec2types.BootModeValuesLegacyBios { + if b.config.BootMode == "legacy-bios" { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`You can't use uefi_data with boot_mode set to "legacy-bios".`)) - } else if b.config.BootMode == "" && b.config.Architecture != ec2types.ArchitectureValuesArm64 { + } else if b.config.BootMode == "" && b.config.Architecture != string(ec2types.ArchitectureValuesArm64) { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`You need boot_mode set to "uefi" to use uefi_data, `+ `"%s" architecture defaults to "legacy-bios".`, b.config.Architecture)) } @@ -470,7 +470,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) }, &StepCreateVolume{ PollingConfig: b.config.PollingConfig, - RootVolumeType: b.config.RootVolumeType, + RootVolumeType: ec2types.VolumeType(b.config.RootVolumeType), RootVolumeSize: b.config.RootVolumeSize, RootVolumeTags: b.config.RootVolumeTags, RootVolumeEncryptBoot: b.config.RootVolumeEncryptBoot, @@ -519,9 +519,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) EnableAMIENASupport: b.config.AMIENASupport, AMISkipBuildRegion: b.config.AMISkipBuildRegion, PollingConfig: b.config.PollingConfig, - BootMode: b.config.BootMode, + BootMode: ec2types.BootModeValues(b.config.BootMode), UefiData: b.config.UefiData, - TpmSupport: b.config.TpmSupport, + TpmSupport: ec2types.TpmSupportValues(b.config.TpmSupport), }, &awscommon.StepAMIRegionCopy{ AccessConfig: &b.config.AccessConfig, diff --git a/builder/chroot/builder.hcl2spec.go b/builder/chroot/builder.hcl2spec.go index 6b4eb85e..cf8168fd 100644 --- a/builder/chroot/builder.hcl2spec.go +++ b/builder/chroot/builder.hcl2spec.go @@ -79,17 +79,17 @@ type FlatConfig struct { PreMountCommands []string `mapstructure:"pre_mount_commands" required:"false" cty:"pre_mount_commands" hcl:"pre_mount_commands"` RootDeviceName *string `mapstructure:"root_device_name" required:"false" cty:"root_device_name" hcl:"root_device_name"` RootVolumeSize *int32 `mapstructure:"root_volume_size" required:"false" cty:"root_volume_size" hcl:"root_volume_size"` - RootVolumeType *types.VolumeType `mapstructure:"root_volume_type" required:"false" cty:"root_volume_type" hcl:"root_volume_type"` + RootVolumeType *string `mapstructure:"root_volume_type" required:"false" cty:"root_volume_type" hcl:"root_volume_type"` SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"` SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"` RootVolumeTags map[string]string `mapstructure:"root_volume_tags" required:"false" cty:"root_volume_tags" hcl:"root_volume_tags"` RootVolumeTag []config.FlatKeyValue `mapstructure:"root_volume_tag" required:"false" cty:"root_volume_tag" hcl:"root_volume_tag"` RootVolumeEncryptBoot *bool `mapstructure:"root_volume_encrypt_boot" required:"false" cty:"root_volume_encrypt_boot" hcl:"root_volume_encrypt_boot"` RootVolumeKmsKeyId *string `mapstructure:"root_volume_kms_key_id" required:"false" cty:"root_volume_kms_key_id" hcl:"root_volume_kms_key_id"` - Architecture *types.ArchitectureValues `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture" hcl:"ami_architecture"` - BootMode *types.BootModeValues `mapstructure:"boot_mode" required:"false" cty:"boot_mode" hcl:"boot_mode"` + Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture" hcl:"ami_architecture"` + BootMode *string `mapstructure:"boot_mode" required:"false" cty:"boot_mode" hcl:"boot_mode"` UefiData *string `mapstructure:"uefi_data" required:"false" cty:"uefi_data" hcl:"uefi_data"` - TpmSupport *types.TpmSupportValues `mapstructure:"tpm_support" required:"false" cty:"tpm_support" hcl:"tpm_support"` + TpmSupport *string `mapstructure:"tpm_support" required:"false" cty:"tpm_support" hcl:"tpm_support"` } // FlatMapstructure returns a new FlatConfig. diff --git a/builder/chroot/step_instance_info.go b/builder/chroot/step_instance_info.go index 34eeda80..7c705045 100644 --- a/builder/chroot/step_instance_info.go +++ b/builder/chroot/step_instance_info.go @@ -63,7 +63,7 @@ func (s *StepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) mu } instance := instancesResp.Reservations[0].Instances[0] - state.Put("instance", instance) + state.Put("instance", &instance) return multistep.ActionContinue } diff --git a/builder/chroot/step_register_ami.go b/builder/chroot/step_register_ami.go index fab02143..cbfbd5c6 100644 --- a/builder/chroot/step_register_ami.go +++ b/builder/chroot/step_register_ami.go @@ -162,7 +162,7 @@ func buildBaseRegisterOpts(config *Config, sourceImage *ec2types.Image, rootVolu if config.FromScratch { return &ec2.RegisterImageInput{ Name: &amiName, - Architecture: config.Architecture, + Architecture: ec2types.ArchitectureValues(config.Architecture), RootDeviceName: aws.String(rootDeviceName), VirtualizationType: aws.String(string(config.AMIVirtType)), BlockDeviceMappings: newMappings, diff --git a/builder/common/access_config.go b/builder/common/access_config.go index 8e474ba3..d37e7918 100644 --- a/builder/common/access_config.go +++ b/builder/common/access_config.go @@ -214,7 +214,7 @@ type AccessConfig struct { func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*aws.Config, error) { // Reload values into the config used by the Packer-Terraform shared SDK - assumeRoles := []awsbase.AssumeRole{} + var assumeRoles []awsbase.AssumeRole if c.AssumeRole.AssumeRoleARN != "" { awsbaseAssumeRole := awsbase.AssumeRole{ RoleARN: c.AssumeRole.AssumeRoleARN, @@ -355,6 +355,7 @@ func (c *AccessConfig) Prepare(packerConfig *common.PackerConfig) []error { c.PollingConfig = new(AWSPollingConfig) } c.PollingConfig.LogEnvOverrideWarnings() + c.PollingConfig.Prepare() // Default MaxRetries to 10, to make throttling issues less likely. The // Aws sdk defaults this to 3, which regularly gets tripped by users. diff --git a/builder/common/block_device.go b/builder/common/block_device.go index b70f8268..c5286911 100644 --- a/builder/common/block_device.go +++ b/builder/common/block_device.go @@ -104,7 +104,7 @@ type BlockDevice struct { // The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2 // for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, // sc1 for Cold HDD, and standard for Magnetic volumes. - VolumeType ec2types.VolumeType `mapstructure:"volume_type" required:"false"` + VolumeType string `mapstructure:"volume_type" required:"false"` // The size of the volume, in GiB. Required if not specifying a // snapshot_id. VolumeSize int32 `mapstructure:"volume_size" required:"false"` @@ -152,20 +152,20 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() ec2types.BlockDevice } if blockDevice.VolumeType != "" { - ebsBlockDevice.VolumeType = blockDevice.VolumeType + ebsBlockDevice.VolumeType = ec2types.VolumeType(blockDevice.VolumeType) } if blockDevice.VolumeSize > 0 { ebsBlockDevice.VolumeSize = aws.Int32(blockDevice.VolumeSize) } - switch blockDevice.VolumeType { + switch ec2types.VolumeType(blockDevice.VolumeType) { case ec2types.VolumeTypeIo1, ec2types.VolumeTypeIo2, ec2types.VolumeTypeGp3: ebsBlockDevice.Iops = blockDevice.IOPS } // Throughput is only valid for gp3 types - if blockDevice.VolumeType == ec2types.VolumeTypeGp3 { + if ec2types.VolumeType(blockDevice.VolumeType) == ec2types.VolumeTypeGp3 { ebsBlockDevice.Throughput = blockDevice.Throughput } @@ -201,7 +201,7 @@ func (b *BlockDevice) Prepare(ctx *interpolate.Context) error { "true` when setting a kms_key_id.", b.DeviceName) } - if ratio, ok := iopsRatios[b.VolumeType]; b.VolumeSize != 0 && ok { + if ratio, ok := iopsRatios[ec2types.VolumeType(b.VolumeType)]; b.VolumeSize != 0 && ok { if b.IOPS != nil && (*b.IOPS/b.VolumeSize > ratio) { return fmt.Errorf("%s: the maximum ratio of provisioned IOPS to requested volume size "+ "(in GiB) is %v:1 for %s volumes", b.DeviceName, ratio, b.VolumeType) @@ -213,7 +213,7 @@ func (b *BlockDevice) Prepare(ctx *interpolate.Context) error { } } - if b.VolumeType == "gp3" { + if ec2types.VolumeType(b.VolumeType) == ec2types.VolumeTypeGp3 { if b.Throughput != nil && (*b.Throughput < minThroughput || *b.Throughput > maxThroughput) { return fmt.Errorf("Throughput must be between %d and %d for device %s", minThroughput, maxThroughput, b.DeviceName) diff --git a/builder/common/block_device.hcl2spec.go b/builder/common/block_device.hcl2spec.go index 5be924cf..3b7dd2a5 100644 --- a/builder/common/block_device.hcl2spec.go +++ b/builder/common/block_device.hcl2spec.go @@ -3,7 +3,6 @@ package common import ( - "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/hcl/v2/hcldec" "github.com/zclconf/go-cty/cty" ) @@ -11,17 +10,17 @@ import ( // FlatBlockDevice is an auto-generated flat version of BlockDevice. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatBlockDevice struct { - DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"` - DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"` - Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"` - IOPS *int32 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"` - NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"` - SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"` - Throughput *int32 `mapstructure:"throughput" required:"false" cty:"throughput" hcl:"throughput"` - VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"` - VolumeType *types.VolumeType `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"` - VolumeSize *int32 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"` - KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"` + DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"` + DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"` + Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"` + IOPS *int32 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"` + NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"` + SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"` + Throughput *int32 `mapstructure:"throughput" required:"false" cty:"throughput" hcl:"throughput"` + VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"` + VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"` + VolumeSize *int32 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"` + KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"` } // FlatMapstructure returns a new FlatBlockDevice. diff --git a/builder/common/block_device_test.go b/builder/common/block_device_test.go index ac5969ae..f75262e0 100644 --- a/builder/common/block_device_test.go +++ b/builder/common/block_device_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" ) @@ -16,18 +17,18 @@ import ( func TestBlockDevice(t *testing.T) { cases := []struct { Config *BlockDevice - Result *ec2types.BlockDeviceMapping + Result ec2types.BlockDeviceMapping }{ { Config: &BlockDevice{ DeviceName: "/dev/sdb", SnapshotId: "snap-1234", - VolumeType: "standard", + VolumeType: string(ec2types.VolumeTypeStandard), VolumeSize: 8, DeleteOnTermination: true, }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ SnapshotId: aws.String("snap-1234"), @@ -43,7 +44,7 @@ func TestBlockDevice(t *testing.T) { VolumeSize: 8, }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeSize: aws.Int32(8), @@ -54,13 +55,13 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), VolumeSize: 8, DeleteOnTermination: true, IOPS: aws.Int32(1000), }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeType: ec2types.VolumeTypeIo1, @@ -73,13 +74,13 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 8, DeleteOnTermination: true, IOPS: aws.Int32(1000), }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeType: ec2types.VolumeTypeIo2, @@ -92,13 +93,13 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp2", + VolumeType: string(ec2types.VolumeTypeGp2), VolumeSize: 8, DeleteOnTermination: true, Encrypted: config.TriTrue, }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeType: ec2types.VolumeTypeGp2, @@ -111,14 +112,14 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp2", + VolumeType: string(ec2types.VolumeTypeGp2), VolumeSize: 8, DeleteOnTermination: true, Encrypted: config.TriTrue, KmsKeyId: "2Fa48a521f-3aff-4b34-a159-376ac5d37812", }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeType: ec2types.VolumeTypeGp2, @@ -132,11 +133,11 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "standard", + VolumeType: string(ec2types.VolumeTypeStandard), DeleteOnTermination: true, }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeType: ec2types.VolumeTypeStandard, @@ -150,7 +151,7 @@ func TestBlockDevice(t *testing.T) { VirtualName: "ephemeral0", }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), VirtualName: aws.String("ephemeral0"), }, @@ -161,7 +162,7 @@ func TestBlockDevice(t *testing.T) { NoDevice: true, }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), NoDevice: aws.String(""), }, @@ -169,7 +170,7 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", + VolumeType: string(ec2types.VolumeTypeGp3), VolumeSize: 8, Throughput: aws.Int32(125), IOPS: aws.Int32(3000), @@ -177,7 +178,7 @@ func TestBlockDevice(t *testing.T) { Encrypted: config.TriTrue, }, - Result: &ec2types.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), Ebs: &ec2types.EbsBlockDevice{ VolumeType: ec2types.VolumeTypeGp3, @@ -196,20 +197,28 @@ func TestBlockDevice(t *testing.T) { var launchBlockDevices BlockDevices = []BlockDevice{*tc.Config} - expected := []*ec2types.BlockDeviceMapping{tc.Result} + expected := []ec2types.BlockDeviceMapping{tc.Result} amiResults := amiBlockDevices.BuildEC2BlockDeviceMappings() - if diff := cmp.Diff(expected, amiResults); diff != "" { + if diff := cmp.Diff(expected, amiResults, cmpopts.IgnoreUnexported(ec2types.BlockDeviceMapping{}, ec2types.EbsBlockDevice{})); diff != "" { t.Fatalf("Bad block device: %s", diff) } launchResults := launchBlockDevices.BuildEC2BlockDeviceMappings() - if diff := cmp.Diff(expected, launchResults); diff != "" { + if diff := cmp.Diff(expected, launchResults, cmpopts.IgnoreUnexported(ec2types.BlockDeviceMapping{}, ec2types.EbsBlockDevice{})); diff != "" { t.Fatalf("Bad block device: %s", diff) } } } +func pointerSlice[T any](s []T) []*T { + result := make([]*T, len(s)) + for i := range s { + result[i] = &s[i] + } + return result +} + func TestIOPSValidation(t *testing.T) { cases := []struct { @@ -221,7 +230,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), IOPS: aws.Int32(1000), }, ok: true, @@ -229,7 +238,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), IOPS: aws.Int32(1000), }, ok: true, @@ -238,7 +247,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), VolumeSize: 50, IOPS: aws.Int32(1000), }, @@ -247,7 +256,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 100, IOPS: aws.Int32(1000), }, @@ -257,7 +266,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), VolumeSize: 10, IOPS: aws.Int32(2000), }, @@ -267,7 +276,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 50, IOPS: aws.Int32(30000), }, @@ -278,7 +287,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 500, IOPS: aws.Int32(99999), }, @@ -289,7 +298,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 50, IOPS: aws.Int32(10), }, @@ -300,7 +309,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", + VolumeType: string(ec2types.VolumeTypeGp3), VolumeSize: 50, Throughput: aws.Int32(125), IOPS: aws.Int32(99999), @@ -312,7 +321,7 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", + VolumeType: string(ec2types.VolumeTypeGp3), VolumeSize: 50, Throughput: aws.Int32(125), IOPS: aws.Int32(10), @@ -348,7 +357,7 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: ec2types.VolumeTypeGp3, + VolumeType: string(ec2types.VolumeTypeGp3), Throughput: aws.Int32(125), IOPS: aws.Int32(3000), }, @@ -357,7 +366,7 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: ec2types.VolumeTypeGp3, + VolumeType: string(ec2types.VolumeTypeGp3), Throughput: aws.Int32(1000), IOPS: aws.Int32(3000), }, @@ -367,7 +376,7 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: ec2types.VolumeTypeGp3, + VolumeType: string(ec2types.VolumeTypeGp3), Throughput: aws.Int32(1001), IOPS: aws.Int32(3000), }, @@ -378,7 +387,7 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: ec2types.VolumeTypeGp3, + VolumeType: string(ec2types.VolumeTypeGp3), Throughput: aws.Int32(124), IOPS: aws.Int32(3000), }, diff --git a/builder/common/boot_mode_validation.go b/builder/common/boot_mode_validation.go index 80832a13..be43cfdf 100644 --- a/builder/common/boot_mode_validation.go +++ b/builder/common/boot_mode_validation.go @@ -10,11 +10,11 @@ import ( ) // IsValidBootMode checks that the bootmode is a value supported by AWS -func IsValidBootMode(bootmode ec2types.BootModeValues) error { +func IsValidBootMode(bootmode string) error { validModes := []ec2types.BootModeValues{ec2types.BootModeValuesLegacyBios, ec2types.BootModeValuesUefi, ec2types.BootModeValuesUefiPreferred} for _, mode := range validModes { - if bootmode == mode { + if bootmode == string(mode) { return nil } } diff --git a/builder/common/boot_mode_validation_test.go b/builder/common/boot_mode_validation_test.go index 43bb0da2..6321596a 100644 --- a/builder/common/boot_mode_validation_test.go +++ b/builder/common/boot_mode_validation_test.go @@ -5,8 +5,6 @@ package common import ( "testing" - - ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" ) func TestIsValidBuildMode(t *testing.T) { @@ -39,7 +37,7 @@ func TestIsValidBuildMode(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := IsValidBootMode(ec2types.BootModeValues(tt.value)) + err := IsValidBootMode(tt.value) if (err != nil) != tt.expectError { t.Errorf("error mismatch, expected %t, got %t", tt.expectError, err != nil) if err != nil { diff --git a/builder/common/interpolate_build_info_test.go b/builder/common/interpolate_build_info_test.go index d44f1545..aa04c06e 100644 --- a/builder/common/interpolate_build_info_test.go +++ b/builder/common/interpolate_build_info_test.go @@ -7,21 +7,21 @@ import ( "reflect" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata" ) -func testImage() *ec2.Image { - return &ec2.Image{ +func testImage() *ec2types.Image { + return &ec2types.Image{ ImageId: aws.String("ami-abcd1234"), CreationDate: aws.String("ami_test_creation_date"), Name: aws.String("ami_test_name"), OwnerId: aws.String("ami_test_owner_id"), ImageOwnerAlias: aws.String("ami_test_owner_alias"), - RootDeviceType: aws.String("ebs"), - Tags: []*ec2.Tag{ + RootDeviceType: ec2types.DeviceTypeEbs, + Tags: []ec2types.Tag{ { Key: aws.String("key-1"), Value: aws.String("value-1"), diff --git a/builder/common/ssh.go b/builder/common/ssh.go index ea2d9f9a..fa89a509 100644 --- a/builder/common/ssh.go +++ b/builder/common/ssh.go @@ -97,7 +97,7 @@ func SSHHost(ctx context.Context, e ec2Describer, sshInterface string, host stri return "", fmt.Errorf("instance not found: %s", *i.InstanceId) } - state.Put("instance", r.Reservations[0].Instances[0]) + state.Put("instance", &r.Reservations[0].Instances[0]) time.Sleep(sshHostSleepDuration) } diff --git a/builder/common/state.go b/builder/common/state.go index 2e021749..1e605ddd 100644 --- a/builder/common/state.go +++ b/builder/common/state.go @@ -94,14 +94,9 @@ func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx context.Context, conn clien ImageIds: []string{imageId}, } log.Printf("Waiting for AMI (%s) to be available...", imageId) - 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. - waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(120)) - } waiter := ec2.NewImageAvailableWaiter(conn) - err := waiter.Wait(ctx, &imageInput, time.Duration(w.MaxTimeout)*time.Second) + maxTimeout := w.WithMaxAttempts(120).MaxTimeout + err := waiter.Wait(ctx, &imageInput, time.Duration(maxTimeout)*time.Second) if err != nil { if strings.Contains(err.Error(), request.WaiterResourceNotReadyErrorCode) { err = fmt.Errorf("Failed with ResourceNotReady error, which can "+ @@ -162,15 +157,9 @@ func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx context.Context, conn clien SnapshotIds: []string{snapshotID}, } - waitOpts := w.getWaiterOptions() - if len(waitOpts) == 0 { - // Bump this default to 30 minutes. - // Large snapshots can take a long time for the copy to s3 - waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(120)) - } - + maxTimeout := w.WithMaxAttempts(120).MaxTimeout waiter := ec2.NewSnapshotCompletedWaiter(conn) - err := waiter.Wait(ctx, &snapInput, time.Duration(w.MaxTimeout)*time.Second) + err := waiter.Wait(ctx, &snapInput, time.Duration(maxTimeout)*time.Second) return err } @@ -810,20 +799,41 @@ type overridableWaitVars struct { awsTimeoutSeconds envInfo } -func (w *AWSPollingConfig) getWaiterOptions() []request.WaiterOption { +func (w *AWSPollingConfig) Prepare() *AWSPollingConfig { envOverrides := getEnvOverrides() - if w.MaxAttempts != 0 { - envOverrides.awsMaxAttempts.Val = w.MaxAttempts - envOverrides.awsMaxAttempts.overridden = true + if w.MaxAttempts == 0 { + if envOverrides.awsMaxAttempts.overridden { + w.MaxAttempts = envOverrides.awsMaxAttempts.Val + } else { + w.MaxAttempts = 40 + } } - if w.DelaySeconds != 0 { - envOverrides.awsPollDelaySeconds.Val = w.DelaySeconds - envOverrides.awsPollDelaySeconds.overridden = true + if w.DelaySeconds == 0 { + if envOverrides.awsPollDelaySeconds.overridden { + w.DelaySeconds = envOverrides.awsPollDelaySeconds.Val + } else { + w.DelaySeconds = 15 + } } + if w.MaxTimeout == 0 { + if envOverrides.awsTimeoutSeconds.overridden { + w.MaxTimeout = envOverrides.awsTimeoutSeconds.Val + } else { + w.MaxTimeout = w.MaxAttempts * w.DelaySeconds + if w.MaxTimeout == 0 { + w.MaxTimeout = 600 + } + } + } + return w +} - waitOpts := applyEnvOverrides(envOverrides) - return waitOpts +func (w *AWSPollingConfig) WithMaxAttempts(maxAttempts int) *AWSPollingConfig { + copy := *w + copy.MaxAttempts = maxAttempts + copy.MaxTimeout = maxAttempts * copy.DelaySeconds + return © } func getOverride(varInfo envInfo) envInfo { diff --git a/builder/common/step_ami_region_copy.go b/builder/common/step_ami_region_copy.go index c1815d9f..fb7c52ea 100644 --- a/builder/common/step_ami_region_copy.go +++ b/builder/common/step_ami_region_copy.go @@ -225,8 +225,18 @@ func (s *StepAMIRegionCopy) amiRegionCopy(ctx context.Context, state multistep.S target, source, keyId string, encrypt *bool) (string, []string, error) { snapshotIds := []string{} - var amiImageId string - regionconn, err := GetEc2Client(ctx, config, target) + var ( + amiImageId string + regionconn clients.Ec2Client + err error + ) + + if s.getRegionConn != nil { + regionconn, err = s.getRegionConn(ctx, config, target) + } else { + // Get the EC2 connection for the target region + regionconn, err = GetEc2Client(ctx, config, target) + } if err != nil { return "", snapshotIds, fmt.Errorf("error getting EC2 client for region (%s): %w", target, err) } diff --git a/builder/common/step_ami_region_copy_test.go b/builder/common/step_ami_region_copy_test.go index 42dfa8b5..fe4fb2d2 100644 --- a/builder/common/step_ami_region_copy_test.go +++ b/builder/common/step_ami_region_copy_test.go @@ -54,7 +54,11 @@ func (m *mockEC2Conn) DescribeImages(ctx context.Context, input *ec2.DescribeIma m.describeImagesCount++ m.lock.Unlock() output := &ec2.DescribeImagesOutput{ - Images: []ec2types.Image{{}}, + Images: []ec2types.Image{ec2types.Image{ + ImageId: aws.String("ami-12345"), + State: ec2types.ImageStateAvailable, + RootDeviceName: aws.String("/dev/sda1"), + }}, } return output, nil } @@ -107,7 +111,8 @@ func tState(ctx context.Context) multistep.StateBag { }) state.Put("amis", map[string]string{"us-east-1": "ami-12345"}) state.Put("snapshots", map[string][]string{"us-east-1": {"snap-0012345"}}) - conn, _ := getMockConn(ctx, &AccessConfig{}, "us-east-2") + accessConfig := FakeAccessConfig() + conn, _ := getMockConn(ctx, accessConfig, "us-east-2") state.Put("ec2", conn) return state } diff --git a/builder/common/step_cleanup_volumes.go b/builder/common/step_cleanup_volumes.go index ec83ce8f..3b281c28 100644 --- a/builder/common/step_cleanup_volumes.go +++ b/builder/common/step_cleanup_volumes.go @@ -7,8 +7,10 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" ) @@ -26,35 +28,35 @@ func (s *StepCleanupVolumes) Run(ctx context.Context, state multistep.StateBag) } func (s *StepCleanupVolumes) Cleanup(state multistep.StateBag) { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(clients.Ec2Client) instanceRaw := state.Get("instance") - var instance *ec2.Instance + var instance *ec2types.Instance if instanceRaw != nil { - instance = instanceRaw.(*ec2.Instance) + instance = instanceRaw.(*ec2types.Instance) } ui := state.Get("ui").(packersdk.Ui) if instance == nil { ui.Say("No volumes to clean up, skipping") return } - + ctx := state.Get("ctx").(context.Context) ui.Say("Cleaning up any extra volumes...") // Collect Volume information from the cached Instance as a map of volume-id // to device name, to compare with save list below - var vl []*string + var vl []string volList := make(map[string]string) for _, bdm := range instance.BlockDeviceMappings { if bdm.Ebs != nil { - vl = append(vl, bdm.Ebs.VolumeId) - volList[*bdm.Ebs.VolumeId] = *bdm.DeviceName + vl = append(vl, aws.ToString(bdm.Ebs.VolumeId)) + volList[aws.ToString(bdm.Ebs.VolumeId)] = aws.ToString(bdm.DeviceName) } } // Using the volume list from the cached Instance, check with AWS for up to // date information on them - resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{ - Filters: []*ec2.Filter{ + resp, err := ec2conn.DescribeVolumes(ctx, &ec2.DescribeVolumesInput{ + Filters: []ec2types.Filter{ { Name: aws.String("volume-id"), Values: vl, @@ -70,8 +72,8 @@ func (s *StepCleanupVolumes) Cleanup(state multistep.StateBag) { // If any of the returned volumes are in a "deleting" stage or otherwise not // available, remove them from the list of volumes for _, v := range resp.Volumes { - if v.State != nil && *v.State != "available" { - delete(volList, *v.VolumeId) + if v.State != ec2types.VolumeStateAvailable { + delete(volList, aws.ToString(v.VolumeId)) } } @@ -93,7 +95,7 @@ func (s *StepCleanupVolumes) Cleanup(state multistep.StateBag) { // Destroy remaining volumes for k := range volList { ui.Say(fmt.Sprintf("Destroying volume (%s)...", k)) - _, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: aws.String(k)}) + _, err := ec2conn.DeleteVolume(ctx, &ec2.DeleteVolumeInput{VolumeId: aws.String(k)}) if err != nil { ui.Say(fmt.Sprintf("Error deleting volume: %s", err)) } diff --git a/builder/common/step_get_password.go b/builder/common/step_get_password.go index 17322d5a..47698a3d 100644 --- a/builder/common/step_get_password.go +++ b/builder/common/step_get_password.go @@ -14,7 +14,9 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -89,8 +91,7 @@ WaitLoop: // In debug-mode, we output the password if s.Debug { - ui.Message(fmt.Sprintf( - "Password (since debug is enabled): %s", s.Comm.WinRMPassword)) + ui.Sayf("Password (since debug is enabled): %s", s.Comm.WinRMPassword) } // store so that we can access this later during provisioning state.Put("winrm_password", s.Comm.WinRMPassword) @@ -102,8 +103,8 @@ WaitLoop: func (s *StepGetPassword) Cleanup(multistep.StateBag) {} func (s *StepGetPassword) waitForPassword(ctx context.Context, state multistep.StateBag) (string, error) { - ec2conn := state.Get("ec2").(*ec2.EC2) - instance := state.Get("instance").(*ec2.Instance) + ec2conn := state.Get("ec2").(clients.Ec2Client) + instance := state.Get("instance").(*ec2types.Instance) privateKey := s.Comm.SSHPrivateKey for { @@ -122,7 +123,7 @@ func (s *StepGetPassword) waitForPassword(ctx context.Context, state multistep.S RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { var err error - resp, err = ec2conn.GetPasswordData(&ec2.GetPasswordDataInput{ + resp, err = ec2conn.GetPasswordData(ctx, &ec2.GetPasswordDataInput{ InstanceId: instance.InstanceId, }) if err != nil { diff --git a/builder/common/step_network_info_test.go b/builder/common/step_network_info_test.go index c365ac8f..52b6cbd1 100644 --- a/builder/common/step_network_info_test.go +++ b/builder/common/step_network_info_test.go @@ -13,6 +13,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -196,7 +197,7 @@ func TestStepNetwork_FilterSubnetsByAZ(t *testing.T) { for _, tt := range testcases { t.Run(tt.name, func(t *testing.T) { subnets := filterSubnetsByAZ(tt.inSubnets, tt.azs) - diff := cmp.Diff(subnets, tt.outSubnets) + diff := cmp.Diff(subnets, tt.outSubnets, cmpopts.IgnoreUnexported(ec2types.Subnet{}, ec2types.BlockPublicAccessStates{}, ec2types.SubnetIpv6CidrBlockAssociation{})) if diff != "" { t.Errorf("subnet mismatch between computed and expected: %s", diff) } diff --git a/builder/common/step_run_source_instance.go b/builder/common/step_run_source_instance.go index c85786dc..f74dc8ed 100644 --- a/builder/common/step_run_source_instance.go +++ b/builder/common/step_run_source_instance.go @@ -354,7 +354,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } } - state.Put("instance", instance) + state.Put("instance", &instance) // instance_id is the generic term used so that users can have access to the // instance id inside of the provisioners, used in step_provision. state.Put("instance_id", instance.InstanceId) diff --git a/builder/common/step_run_spot_instance.go b/builder/common/step_run_spot_instance.go index a72e8477..2b13d5d2 100644 --- a/builder/common/step_run_spot_instance.go +++ b/builder/common/step_run_spot_instance.go @@ -589,7 +589,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } } - state.Put("instance", instance) + state.Put("instance", &instance) // instance_id is the generic term used so that users can have access to the // instance id inside of the provisioners, used in step_provision. state.Put("instance_id", instance.InstanceId) diff --git a/builder/common/step_run_spot_instance_test.go b/builder/common/step_run_spot_instance_test.go index 544b795c..2d4b88ab 100644 --- a/builder/common/step_run_spot_instance_test.go +++ b/builder/common/step_run_spot_instance_test.go @@ -12,6 +12,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -35,7 +36,7 @@ func tStateSpot() multistep.StateBag { func getBasicStep() *StepRunSpotInstance { stepRunSpotInstance := StepRunSpotInstance{ - PollingConfig: new(AWSPollingConfig), + PollingConfig: new(AWSPollingConfig).Prepare(), AssociatePublicIpAddress: confighelper.TriUnset, LaunchMappings: BlockDevices{}, BlockDurationMinutes: 0, @@ -145,6 +146,9 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { } type runSpotEC2ConnMock struct { + //clients.Ec2Client + clients.Ec2Client + CreateLaunchTemplateParams []*ec2.CreateLaunchTemplateInput CreateLaunchTemplateFn func(context.Context, *ec2.CreateLaunchTemplateInput, ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) @@ -212,6 +216,9 @@ func defaultEc2Mock(instanceId, spotRequestId, volumeId, launchTemplateId *strin }, }, }, + State: &ec2types.InstanceState{ + Name: ec2types.InstanceStateNameRunning, + }, } return &runSpotEC2ConnMock{ CreateLaunchTemplateFn: func(ctx context.Context, in *ec2.CreateLaunchTemplateInput, opts ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) { @@ -274,7 +281,7 @@ func TestRun(t *testing.T) { "volume-tag": "volume-tag-value", } - ctx := context.TODO() + ctx := t.Context() action := stepRunSpotInstance.Run(ctx, state) if err := state.Get("error"); err != nil { @@ -329,8 +336,8 @@ func TestRun(t *testing.T) { t.Fatalf("expected fleet-tag: fleet-tag-value") } - if len(ec2Mock.DescribeInstancesParams) != 1 { - t.Fatalf("describeInstancesParams should be invoked once, but invoked %v", len(ec2Mock.DescribeInstancesParams)) + if len(ec2Mock.DescribeInstancesParams) != 2 { + t.Fatalf("describeInstancesParams should be invoked twice, but invoked %v", len(ec2Mock.DescribeInstancesParams)) } if ec2Mock.DescribeInstancesParams[0].InstanceIds[0] != *instanceId { t.Fatalf("instanceId should match from createFleet response") @@ -372,7 +379,7 @@ func TestRun_NoSpotTags(t *testing.T) { "volume-tag": "volume-tag-value", } - ctx := context.TODO() + ctx := t.Context() action := stepRunSpotInstance.Run(ctx, state) if err := state.Get("error"); err != nil { diff --git a/builder/common/step_source_ami_info.go b/builder/common/step_source_ami_info.go index aa09ec58..8ef02de2 100644 --- a/builder/common/step_source_ami_info.go +++ b/builder/common/step_source_ami_info.go @@ -23,7 +23,7 @@ import ( // // Produces: // -// source_image *ec2.Image - the source AMI info +// source_image *ec2types.Image - the source AMI info type StepSourceAMIInfo struct { SourceAmi string EnableAMISriovNetSupport bool diff --git a/builder/common/step_stop_ebs_instance.go b/builder/common/step_stop_ebs_instance.go index 776c9ac2..52207f50 100644 --- a/builder/common/step_stop_ebs_instance.go +++ b/builder/common/step_stop_ebs_instance.go @@ -8,8 +8,11 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors" + "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/retry" @@ -22,8 +25,8 @@ type StepStopEBSBackedInstance struct { } func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) - instance := state.Get("instance").(*ec2.Instance) + ec2conn := state.Get("ec2").(clients.Ec2Client) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) // Skip when it is a spot instance @@ -53,10 +56,10 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta }, RetryDelay: (&retry.Backoff{InitialBackoff: 10 * time.Second, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { - ui.Message("Stopping instance") + ui.Say("Stopping instance") - _, err = ec2conn.StopInstances(&ec2.StopInstancesInput{ - InstanceIds: []*string{instance.InstanceId}, + _, err = ec2conn.StopInstances(ctx, &ec2.StopInstancesInput{ + InstanceIds: []string{aws.ToString(instance.InstanceId)}, }) return err @@ -75,12 +78,10 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta // Wait for the instance to actually stop ui.Say("Waiting for the instance to stop...") - err = ec2conn.WaitUntilInstanceStoppedWithContext(ctx, - &ec2.DescribeInstancesInput{ - InstanceIds: []*string{instance.InstanceId}, - }, - s.PollingConfig.getWaiterOptions()...) - + w := ec2.NewInstanceStoppedWaiter(ec2conn) + err = w.Wait(ctx, &ec2.DescribeInstancesInput{ + InstanceIds: []string{aws.ToString(instance.InstanceId)}, + }, time.Duration(s.PollingConfig.MaxTimeout)) if err != nil { err := fmt.Errorf("Error waiting for instance to stop: %s", err) state.Put("error", err) diff --git a/builder/common/test_helper_funcs.go b/builder/common/test_helper_funcs.go index bb57bdd5..fbfc9225 100644 --- a/builder/common/test_helper_funcs.go +++ b/builder/common/test_helper_funcs.go @@ -17,7 +17,11 @@ func FakeAccessConfig() *AccessConfig { getEC2Connection: func() clients.Ec2Client { return &mockEC2Client{} }, - PollingConfig: new(AWSPollingConfig), + AccessKey: "AKIA12SOME345EXAMPLE", + SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + Token: "accesstoken", + SkipCredsValidation: true, + PollingConfig: new(AWSPollingConfig).Prepare(), } accessConfig.awsConfig = &aws.Config{ Region: "us-east-1", diff --git a/builder/ebs/builder.go b/builder/ebs/builder.go index 15ff88d2..6406ee7d 100644 --- a/builder/ebs/builder.go +++ b/builder/ebs/builder.go @@ -211,7 +211,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) state.Put("config", &b.config) state.Put("access_config", &b.config.AccessConfig) state.Put("ami_config", &b.config.AMIConfig) - state.Put("ec2v2", client) + state.Put("ec2", client) state.Put("iam", iamClient) state.Put("hook", hook) state.Put("ui", ui) diff --git a/builder/ebs/step_create_ami.go b/builder/ebs/step_create_ami.go index fa76dc95..7fb7584f 100644 --- a/builder/ebs/step_create_ami.go +++ b/builder/ebs/step_create_ami.go @@ -35,7 +35,7 @@ type stepCreateAMI struct { func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) instance := state.Get("instance").(ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) @@ -181,7 +181,7 @@ func (s *stepCreateAMI) Cleanup(state multistep.StateBag) { return } - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Deregistering the AMI and deleting associated snapshots because " + diff --git a/builder/ebssurrogate/builder.go b/builder/ebssurrogate/builder.go index aed268b8..96389290 100644 --- a/builder/ebssurrogate/builder.go +++ b/builder/ebssurrogate/builder.go @@ -249,7 +249,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) state.Put("config", &b.config) state.Put("access_config", &b.config.AccessConfig) state.Put("ami_config", &b.config.AMIConfig) - state.Put("ec2v2", client) + state.Put("ec2", client) state.Put("iam", iamClient) state.Put("hook", hook) state.Put("ui", ui) diff --git a/builder/ebssurrogate/step_create_ami.go b/builder/ebssurrogate/step_create_ami.go index e618770f..b8f12840 100644 --- a/builder/ebssurrogate/step_create_ami.go +++ b/builder/ebssurrogate/step_create_ami.go @@ -38,7 +38,7 @@ type StepCreateAMI struct { func (s *StepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) instance := state.Get("instance").(ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) @@ -216,7 +216,7 @@ func (s *StepCreateAMI) Cleanup(state multistep.StateBag) { return } - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Deregistering the AMI and deleting associated snapshots because " + diff --git a/builder/ebssurrogate/step_register_ami.go b/builder/ebssurrogate/step_register_ami.go index 6274977b..7238afbb 100644 --- a/builder/ebssurrogate/step_register_ami.go +++ b/builder/ebssurrogate/step_register_ami.go @@ -37,7 +37,7 @@ type StepRegisterAMI struct { func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) snapshotIds := state.Get("snapshot_ids").(map[string]string) ui := state.Get("ui").(packersdk.Ui) @@ -145,7 +145,7 @@ func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) { return } - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Deregistering the AMI because cancellation or error...") diff --git a/builder/ebssurrogate/step_snapshot_volumes.go b/builder/ebssurrogate/step_snapshot_volumes.go index aae4ca14..a8be3345 100644 --- a/builder/ebssurrogate/step_snapshot_volumes.go +++ b/builder/ebssurrogate/step_snapshot_volumes.go @@ -37,7 +37,7 @@ type StepSnapshotVolumes struct { } func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName string, state multistep.StateBag) error { - ec2conn := state.Get("ec2v2").(clients.Ec2Client) + ec2conn := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) ui := state.Get("ui").(packersdk.Ui) instance := state.Get("instance").(ec2types.Instance) @@ -140,7 +140,7 @@ func (s *StepSnapshotVolumes) Cleanup(state multistep.StateBag) { _, halted := state.GetOk(multistep.StateHalted) if cancelled || halted { - ec2conn := state.Get("ec2v2").(clients.Ec2Client) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Removing snapshots since we cancelled or halted...") s.snapshotMutex.Lock() diff --git a/builder/ebssurrogate/step_swap_volumes.go b/builder/ebssurrogate/step_swap_volumes.go index af335da2..a1d1d143 100644 --- a/builder/ebssurrogate/step_swap_volumes.go +++ b/builder/ebssurrogate/step_swap_volumes.go @@ -29,7 +29,7 @@ type StepSwapVolumes struct { } func (s *StepSwapVolumes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) instance := state.Get("instance").(ec2types.Instance) @@ -143,7 +143,7 @@ func (s *StepSwapVolumes) detachVolume(ctx context.Context, ec2Client clients.Ec func (s *StepSwapVolumes) Cleanup(state multistep.StateBag) { ctx := context.TODO() - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) instance := state.Get("instance").(ec2types.Instance) ui.Say("Cleaning up any detached volumes with delete_on_termination set to true...") diff --git a/builder/ebsvolume/builder.go b/builder/ebsvolume/builder.go index 5e195c15..719cd9de 100644 --- a/builder/ebsvolume/builder.go +++ b/builder/ebsvolume/builder.go @@ -194,7 +194,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) state := new(multistep.BasicStateBag) state.Put("config", &b.config) state.Put("access_config", &b.config.AccessConfig) - state.Put("ec2v2", client) + state.Put("ec2", client) state.Put("iam", iamClient) state.Put("hook", hook) state.Put("ui", ui) diff --git a/builder/ebsvolume/step_snapshot_ebs_volumes.go b/builder/ebsvolume/step_snapshot_ebs_volumes.go index 87a6deba..3d8d42e3 100644 --- a/builder/ebsvolume/step_snapshot_ebs_volumes.go +++ b/builder/ebsvolume/step_snapshot_ebs_volumes.go @@ -28,8 +28,8 @@ type stepSnapshotEBSVolumes struct { } func (s *stepSnapshotEBSVolumes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) + ec2Client := state.Get("ec2").(clients.Ec2Client) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packer.Ui) s.snapshotMap = make(map[string]*BlockDevice) diff --git a/builder/ebsvolume/step_snapshot_ebs_volumes_test.go b/builder/ebsvolume/step_snapshot_ebs_volumes_test.go index 2903bcdf..b179d445 100644 --- a/builder/ebsvolume/step_snapshot_ebs_volumes_test.go +++ b/builder/ebsvolume/step_snapshot_ebs_volumes_test.go @@ -69,10 +69,10 @@ func tState(t *testing.T) multistep.StateBag { // state.Put("snapshots", map[string][]string{"us-east-1": {"snap-0012345"}}) conn, _ := getMockConn(&common.AccessConfig{}, "us-east-2") - state.Put("ec2v2", conn) + state.Put("ec2", conn) // Store a fake instance that contains a block device that matches the // volumes defined in the config above - state.Put("instance", ec2types.Instance{ + state.Put("instance", &ec2types.Instance{ InstanceId: aws.String("instance-id"), BlockDeviceMappings: []ec2types.InstanceBlockDeviceMapping{ { diff --git a/builder/ebsvolume/step_tag_ebs_volumes.go b/builder/ebsvolume/step_tag_ebs_volumes.go index 910809aa..8485b6f7 100644 --- a/builder/ebsvolume/step_tag_ebs_volumes.go +++ b/builder/ebsvolume/step_tag_ebs_volumes.go @@ -24,7 +24,7 @@ type stepTagEBSVolumes struct { } func (s *stepTagEBSVolumes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) instance := state.Get("instance").(ec2types.Instance) region := state.Get("region").(string) ui := state.Get("ui").(packersdk.Ui) diff --git a/builder/instance/step_bundle_volume.go b/builder/instance/step_bundle_volume.go index 602fa2c3..b1c9a2ae 100644 --- a/builder/instance/step_bundle_volume.go +++ b/builder/instance/step_bundle_volume.go @@ -7,7 +7,7 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" @@ -30,7 +30,7 @@ type StepBundleVolume struct { func (s *StepBundleVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { comm := state.Get("communicator").(packersdk.Communicator) config := state.Get("config").(*Config) - instance := state.Get("instance").(*ec2.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) x509RemoteCertPath := state.Get("x509RemoteCertPath").(string) x509RemoteKeyPath := state.Get("x509RemoteKeyPath").(string) @@ -39,7 +39,7 @@ func (s *StepBundleVolume) Run(ctx context.Context, state multistep.StateBag) mu var err error config.ctx.Data = bundleCmdData{ AccountId: config.AccountId, - Architecture: *instance.Architecture, + Architecture: string(instance.Architecture), CertPath: x509RemoteCertPath, Destination: config.BundleDestination, KeyPath: x509RemoteKeyPath, diff --git a/common/ssh.go b/common/ssh.go index ff50cfac..e910db82 100644 --- a/common/ssh.go +++ b/common/ssh.go @@ -41,7 +41,7 @@ func SSHHost(ctx context.Context, e ec2Describer, sshInterface string, host stri const tries = 2 // <= with current structure to check result of describing `tries` times for j := 0; j <= tries; j++ { - i := state.Get("instance").(ec2types.Instance) + i := state.Get("instance").(*ec2types.Instance) if sshInterface != "" { switch sshInterface { case "public_ip": @@ -94,7 +94,7 @@ func SSHHost(ctx context.Context, e ec2Describer, sshInterface string, host stri return "", fmt.Errorf("instance not found: %s", *i.InstanceId) } - state.Put("instance", r.Reservations[0].Instances[0]) + state.Put("instance", &r.Reservations[0].Instances[0]) time.Sleep(sshHostSleepDuration) } diff --git a/common/ssh_test.go b/common/ssh_test.go index 0170f9a7..7e0873be 100644 --- a/common/ssh_test.go +++ b/common/ssh_test.go @@ -89,7 +89,7 @@ func testSSHHost(t *testing.T, allowTries int, vpcId string, sshInterface string f := SSHHost(context.Background(), e, sshInterface, sshHostOverride) st := &multistep.BasicStateBag{} - st.Put("instance", ec2types.Instance{ + st.Put("instance", &ec2types.Instance{ InstanceId: aws.String("instance-id"), }) diff --git a/common/step_ami_region_copy.go b/common/step_ami_region_copy.go index b134ccf3..a17c1b7a 100644 --- a/common/step_ami_region_copy.go +++ b/common/step_ami_region_copy.go @@ -158,7 +158,7 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m } func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) if len(s.toDelete) == 0 { diff --git a/common/step_ami_region_copy_test.go b/common/step_ami_region_copy_test.go index f27ce395..9fb3ab37 100644 --- a/common/step_ami_region_copy_test.go +++ b/common/step_ami_region_copy_test.go @@ -97,7 +97,7 @@ func tState() multistep.StateBag { state.Put("amis", map[string]string{"us-east-1": "ami-12345"}) state.Put("snapshots", map[string][]string{"us-east-1": {"snap-0012345"}}) conn, _ := getMockConn(context.TODO(), &AccessConfig{}, "us-east-2") - state.Put("ec2v2", conn) + state.Put("ec2", conn) return state } diff --git a/common/step_cleanup_volumes.go b/common/step_cleanup_volumes.go index 834f1df5..b267bb69 100644 --- a/common/step_cleanup_volumes.go +++ b/common/step_cleanup_volumes.go @@ -29,7 +29,7 @@ func (s *StepCleanupVolumes) Run(ctx context.Context, state multistep.StateBag) func (s *StepCleanupVolumes) Cleanup(state multistep.StateBag) { ctx := context.TODO() - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) instanceRaw := state.Get("instance") var instance ec2types.Instance if instanceRaw != nil { diff --git a/common/step_create_ssm_tunnel.go b/common/step_create_ssm_tunnel.go index cee9a7ea..4c658eae 100644 --- a/common/step_create_ssm_tunnel.go +++ b/common/step_create_ssm_tunnel.go @@ -76,7 +76,7 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) ssmCtx, ssmCancel := context.WithCancel(ctx) s.stopSSMCommand = ssmCancel - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ssmconn := ssm.NewFromConfig(s.AwsConfig) session := pssm.Session{ diff --git a/common/step_get_password.go b/common/step_get_password.go index 4b504434..78d7a6d2 100644 --- a/common/step_get_password.go +++ b/common/step_get_password.go @@ -104,7 +104,7 @@ WaitLoop: func (s *StepGetPassword) Cleanup(multistep.StateBag) {} func (s *StepGetPassword) waitForPassword(ctx context.Context, state multistep.StateBag) (string, error) { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) instance := state.Get("instance").(ec2types.Instance) privateKey := s.Comm.SSHPrivateKey diff --git a/common/step_iam_instance_profile.go b/common/step_iam_instance_profile.go index bd3970ec..3214d713 100644 --- a/common/step_iam_instance_profile.go +++ b/common/step_iam_instance_profile.go @@ -179,7 +179,7 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB ui.Say("Waiting for the change to propagate because of eventual consistency...") - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) sourceImageRaw, exists := state.GetOk("source_image") if !exists { err := fmt.Errorf("source_image not available in state for IAM validation") diff --git a/common/step_key_pair.go b/common/step_key_pair.go index ca9a55e4..5f90b56a 100644 --- a/common/step_key_pair.go +++ b/common/step_key_pair.go @@ -63,7 +63,7 @@ func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multist return multistep.ActionContinue } - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) var keyResp *ec2.CreateKeyPairOutput ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.Comm.SSHTemporaryKeyPairName)) @@ -138,7 +138,7 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) { return } ctx := context.TODO() - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) // Remove the keypair diff --git a/common/step_modify_ebs_instance.go b/common/step_modify_ebs_instance.go index 264e0bcb..b9d885a5 100644 --- a/common/step_modify_ebs_instance.go +++ b/common/step_modify_ebs_instance.go @@ -23,7 +23,7 @@ type StepModifyEBSBackedInstance struct { } func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) instance := state.Get("instance").(ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) diff --git a/common/step_network_info.go b/common/step_network_info.go index 41676e75..9e96e2e6 100644 --- a/common/step_network_info.go +++ b/common/step_network_info.go @@ -59,7 +59,7 @@ func mostFreeSubnet(subnets []ec2types.Subnet) ec2types.Subnet { } func (s *StepNetworkInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) // Set VpcID if none was specified but filters are defined in the template. diff --git a/common/step_pre_validate.go b/common/step_pre_validate.go index f8f150ae..6296964b 100644 --- a/common/step_pre_validate.go +++ b/common/step_pre_validate.go @@ -97,7 +97,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul return multistep.ActionContinue } - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) // Validate VPC settings for non-default VPCs ui.Say("Prevalidating any provided VPC information") diff --git a/common/step_run_source_instance.go b/common/step_run_source_instance.go index 839a8ac5..03e73059 100644 --- a/common/step_run_source_instance.go +++ b/common/step_run_source_instance.go @@ -62,7 +62,7 @@ type StepRunSourceInstance struct { } func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) securityGroupIds := state.Get("securityGroupIds").([]string) @@ -357,7 +357,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } } - state.Put("instance", instance) + state.Put("instance", &instance) // instance_id is the generic term used so that users can have access to the // instance id inside of the provisioners, used in step_provision. state.Put("instance_id", instance.InstanceId) @@ -481,7 +481,7 @@ func waitForInstanceReadiness( func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ctx := context.TODO() // Terminate the source instance if it exists diff --git a/common/step_run_spot_instance.go b/common/step_run_spot_instance.go index 38dd2a23..3404e645 100644 --- a/common/step_run_spot_instance.go +++ b/common/step_run_spot_instance.go @@ -217,7 +217,7 @@ func (s *StepRunSpotInstance) LoadUserData() (string, error) { } func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Launching a spot AWS instance...") @@ -593,7 +593,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } } - state.Put("instance", instance) + state.Put("instance", &instance) // instance_id is the generic term used so that users can have access to the // instance id inside of the provisioners, used in step_provision. state.Put("instance_id", instance.InstanceId) @@ -602,7 +602,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } func (s *StepRunSpotInstance) Cleanup(state multistep.StateBag) { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) launchTemplateName := state.Get("launchTemplateName").(string) diff --git a/common/step_run_spot_instance_test.go b/common/step_run_spot_instance_test.go index fb9d198b..494723dc 100644 --- a/common/step_run_spot_instance_test.go +++ b/common/step_run_spot_instance_test.go @@ -10,11 +10,9 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" - - "github.com/aws/aws-sdk-go-v2/service/ec2" - "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -152,21 +150,21 @@ type runSpotEC2ConnMock struct { clients.Ec2Client CreateLaunchTemplateParams []*ec2.CreateLaunchTemplateInput - CreateLaunchTemplateFn func(*ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) + CreateLaunchTemplateFn func(context.Context, *ec2.CreateLaunchTemplateInput, ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) CreateFleetParams []*ec2.CreateFleetInput - CreateFleetFn func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) + CreateFleetFn func(context.Context, *ec2.CreateFleetInput, ...func(*ec2.Options)) (*ec2.CreateFleetOutput, error) CreateTagsParams []*ec2.CreateTagsInput - CreateTagsFn func(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) + CreateTagsFn func(context.Context, *ec2.CreateTagsInput, ...func(*ec2.Options)) (*ec2.CreateTagsOutput, error) DescribeInstancesParams []*ec2.DescribeInstancesInput - DescribeInstancesFn func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) + DescribeInstancesFn func(context.Context, *ec2.DescribeInstancesInput, ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) } func (m *runSpotEC2ConnMock) CreateLaunchTemplate(ctx context.Context, params *ec2.CreateLaunchTemplateInput, optFns ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) { m.CreateLaunchTemplateParams = append(m.CreateLaunchTemplateParams, params) - resp, err := m.CreateLaunchTemplateFn(params) + resp, err := m.CreateLaunchTemplateFn(ctx, params, optFns...) return resp, err } @@ -174,7 +172,7 @@ func (m *runSpotEC2ConnMock) CreateFleet(ctx context.Context, params *ec2.Create optFns ...func(options *ec2.Options)) (*ec2.CreateFleetOutput, error) { m.CreateFleetParams = append(m.CreateFleetParams, params) if m.CreateFleetFn != nil { - resp, err := m.CreateFleetFn(params) + resp, err := m.CreateFleetFn(ctx, params, optFns...) return resp, err } else { return nil, nil @@ -184,7 +182,7 @@ func (m *runSpotEC2ConnMock) CreateFleet(ctx context.Context, params *ec2.Create func (m *runSpotEC2ConnMock) DescribeInstances(ctx context.Context, params *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) { m.DescribeInstancesParams = append(m.DescribeInstancesParams, params) if m.DescribeInstancesFn != nil { - resp, err := m.DescribeInstancesFn(params) + resp, err := m.DescribeInstancesFn(ctx, params, optFns...) return resp, err } else { return nil, nil @@ -199,7 +197,7 @@ func (m *runSpotEC2ConnMock) DescribeInstances(ctx context.Context, params *ec2. func (m *runSpotEC2ConnMock) CreateTags(ctx context.Context, params *ec2.CreateTagsInput, optFns ...func(*ec2.Options)) (*ec2.CreateTagsOutput, error) { m.CreateTagsParams = append(m.CreateTagsParams, params) if m.CreateTagsFn != nil { - resp, err := m.CreateTagsFn(params) + resp, err := m.CreateTagsFn(ctx, params, optFns...) return resp, err } else { return nil, nil @@ -222,7 +220,7 @@ func defaultEc2Mock(instanceId, spotRequestId, volumeId, launchTemplateId *strin }, } return &runSpotEC2ConnMock{ - CreateLaunchTemplateFn: func(in *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { + CreateLaunchTemplateFn: func(ctx context.Context, in *ec2.CreateLaunchTemplateInput, optFns ...func(*ec2.Options)) (*ec2.CreateLaunchTemplateOutput, error) { return &ec2.CreateLaunchTemplateOutput{ LaunchTemplate: &ec2types.LaunchTemplate{ LaunchTemplateId: launchTemplateId, @@ -230,7 +228,7 @@ func defaultEc2Mock(instanceId, spotRequestId, volumeId, launchTemplateId *strin Warning: nil, }, nil }, - CreateFleetFn: func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) { + CreateFleetFn: func(ctx context.Context, in *ec2.CreateFleetInput, optFns ...func(*ec2.Options)) (*ec2.CreateFleetOutput, error) { return &ec2.CreateFleetOutput{ Errors: nil, FleetId: nil, @@ -241,7 +239,7 @@ func defaultEc2Mock(instanceId, spotRequestId, volumeId, launchTemplateId *strin }, }, nil }, - DescribeInstancesFn: func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { + DescribeInstancesFn: func(ctx context.Context, input *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error) { return &ec2.DescribeInstancesOutput{ NextToken: nil, Reservations: []ec2types.Reservation{ @@ -265,7 +263,7 @@ func TestRun(t *testing.T) { uiMock := packersdk.TestUi(t) state := tStateSpot() - state.Put("ec2v2", ec2Mock) + state.Put("ec2", ec2Mock) state.Put("ui", uiMock) state.Put("source_image", testImage()) @@ -374,7 +372,7 @@ func TestRun_NoSpotTags(t *testing.T) { uiMock := packersdk.TestUi(t) state := tStateSpot() - state.Put("ec2v2", ec2Mock) + state.Put("ec2", ec2Mock) state.Put("ui", uiMock) state.Put("source_image", testImage()) diff --git a/common/step_security_group.go b/common/step_security_group.go index 016415be..38c71f38 100644 --- a/common/step_security_group.go +++ b/common/step_security_group.go @@ -38,7 +38,7 @@ type StepSecurityGroup struct { } func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) ui := state.Get("ui").(packersdk.Ui) vpcId := state.Get("vpc_id").(string) @@ -241,7 +241,7 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) { return } ctx := context.TODO() - ec2conn := state.Get("ec2v2").(clients.Ec2Client) + ec2conn := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) ui.Say("Deleting temporary security group...") diff --git a/common/step_source_ami_info.go b/common/step_source_ami_info.go index d2e6424b..66806f2c 100644 --- a/common/step_source_ami_info.go +++ b/common/step_source_ami_info.go @@ -10,7 +10,7 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/service/ec2" - "github.com/aws/aws-sdk-go-v2/service/ec2/types" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -22,7 +22,7 @@ import ( // // Produces: // -// source_image *ec2.Image - the source AMI info +// source_image *ec2types.Image - the source AMI info type StepSourceAMIInfo struct { SourceAmi string EnableAMISriovNetSupport bool @@ -32,7 +32,7 @@ type StepSourceAMIInfo struct { IncludeDeprecated bool } -type imageSort []types.Image +type imageSort []ec2types.Image func (a imageSort) Len() int { return len(a) } func (a imageSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } @@ -43,14 +43,14 @@ func (a imageSort) Less(i, j int) bool { } // Returns the most recent AMI out of a slice of images. -func mostRecentAmi(images []types.Image) types.Image { +func mostRecentAmi(images []ec2types.Image) ec2types.Image { sortedImages := images sort.Sort(imageSort(sortedImages)) return sortedImages[len(sortedImages)-1] } func (s *StepSourceAMIInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - client := state.Get("ec2v2").(clients.Ec2Client) + client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) params := &ec2.DescribeImagesInput{ @@ -87,14 +87,14 @@ func (s *StepSourceAMIInfo) Run(ctx context.Context, state multistep.StateBag) m func (s *StepSourceAMIInfo) Cleanup(multistep.StateBag) {} -func (s *StepSourceAMIInfo) canEnableEnhancedNetworking(image *types.Image) error { +func (s *StepSourceAMIInfo) canEnableEnhancedNetworking(image *ec2types.Image) error { if s.AMIVirtType == "hvm" { return nil } if s.AMIVirtType != "" { return fmt.Errorf("Cannot enable enhanced networking, AMIVirtType '%s' is not HVM", s.AMIVirtType) } - if image.VirtualizationType != types.VirtualizationTypeHvm { + if image.VirtualizationType != ec2types.VirtualizationTypeHvm { return fmt.Errorf("Cannot enable enhanced networking, source AMI '%s' is not HVM", s.SourceAmi) } return nil diff --git a/common/step_stop_ebs_instance.go b/common/step_stop_ebs_instance.go index 27d6d2fc..883176ce 100644 --- a/common/step_stop_ebs_instance.go +++ b/common/step_stop_ebs_instance.go @@ -25,7 +25,7 @@ type StepStopEBSBackedInstance struct { } func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) + ec2Client := state.Get("ec2").(clients.Ec2Client) instance := state.Get("instance").(ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) diff --git a/docs-partials/builder/chroot/Config-not-required.mdx b/docs-partials/builder/chroot/Config-not-required.mdx index 72da9373..49b67dcc 100644 --- a/docs-partials/builder/chroot/Config-not-required.mdx +++ b/docs-partials/builder/chroot/Config-not-required.mdx @@ -75,7 +75,7 @@ resulting AMI. Default size is the snapshot size of the source_ami unless from_scratch is true, in which case this field must be defined. -- `root_volume_type` (ec2types.VolumeType) - The type of EBS volume for the chroot environment and resulting AMI. The +- `root_volume_type` (string) - The type of EBS volume for the chroot environment and resulting AMI. The default value is the type of the source_ami, unless from_scratch is true, in which case the default value is gp2. You can only specify io1 if building based on top of a source_ami which is also io1. @@ -151,10 +151,10 @@ This field is validated by Packer, when using an alias, you will have to prefix `kms_key_id` with `alias/`. -- `ami_architecture` (ec2types.ArchitectureValues) - what architecture to use when registering the final AMI; valid options +- `ami_architecture` (string) - what architecture to use when registering the final AMI; valid options are "arm64", "arm64_mac", "i386", "x86_64", or "x86_64_mac". Defaults to "x86_64". -- `boot_mode` (ec2types.BootModeValues) - The boot mode. Valid options are `legacy-bios` and `uefi`. See the documentation on +- `boot_mode` (string) - The boot mode. Valid options are `legacy-bios` and `uefi`. See the documentation on [boot modes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ami-boot.html) for more information. Defaults to `legacy-bios` when `ami_architecture` is `x86_64` and `uefi` when `ami_architecture` is `arm64`. @@ -162,7 +162,7 @@ - `uefi_data` (string) - Base64 representation of the non-volatile UEFI variable store. For more information see [AWS documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/uefi-secure-boot-optionB.html). -- `tpm_support` (ec2types.TpmSupportValues) - NitroTPM Support. Valid options are `v2.0`. See the documentation on +- `tpm_support` (string) - NitroTPM Support. Valid options are `v2.0`. See the documentation on [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for more information. Only enabled if a valid option is provided, otherwise ignored. diff --git a/docs-partials/builder/common/BlockDevice-not-required.mdx b/docs-partials/builder/common/BlockDevice-not-required.mdx index a8fd48d5..6878d738 100644 --- a/docs-partials/builder/common/BlockDevice-not-required.mdx +++ b/docs-partials/builder/common/BlockDevice-not-required.mdx @@ -37,7 +37,7 @@ The volume virtual_name should be in the `ephemeral[0-23]` form, e.g. ephemeral1 -- `volume_type` (ec2types.VolumeType) - The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2 +- `volume_type` (string) - The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2 for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. From 0ec45a434a3083a20672ba3bcddbd8b211571c00 Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Thu, 14 May 2026 18:55:35 +0200 Subject: [PATCH 4/8] fix: AW SDK v2 - update Golang version --- .go-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.go-version b/.go-version index 7ae54502..958bb4d7 100644 --- a/.go-version +++ b/.go-version @@ -1,2 +1,2 @@ -1.24.0 +1.26.0 From d770e7def6702477d6452bcdbe4e0eedbcabc28e Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Mon, 18 May 2026 10:51:02 +0200 Subject: [PATCH 5/8] fix: Added regenerated docs, update golang-ci-lint version --- .github/workflows/go-validate.yml | 7 +++-- .web-docs/components/builder/chroot/README.md | 17 +++++++---- .web-docs/components/builder/ebs/README.md | 27 ++++++++++------- .../components/builder/ebssurrogate/README.md | 27 ++++++++++------- .../components/builder/ebsvolume/README.md | 23 +++++++++------ .../components/builder/instance/README.md | 29 +++++++++++-------- 6 files changed, 78 insertions(+), 52 deletions(-) diff --git a/.github/workflows/go-validate.yml b/.github/workflows/go-validate.yml index c996df46..5a8d8af7 100644 --- a/.github/workflows/go-validate.yml +++ b/.github/workflows/go-validate.yml @@ -10,7 +10,7 @@ name: "Go Validate" on: push: branches: - - 'main' + - "main" pull_request: permissions: @@ -23,7 +23,7 @@ jobs: go-version: ${{ steps.get-go-version.outputs.go-version }} steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - name: 'Determine Go version' + - name: "Determine Go version" id: get-go-version run: | echo "Found Go $(cat .go-version)" @@ -51,7 +51,8 @@ jobs: go-version: ${{ needs.get-go-version.outputs.go-version }} - uses: golangci/golangci-lint-action@82d40c283aeb1f2b6595839195e95c2d6a49081b # v5.0.0 with: - version: v1.64.8 + version: v2.12.2 + install-mode: goinstall only-new-issues: true check-fmt: needs: diff --git a/.web-docs/components/builder/chroot/README.md b/.web-docs/components/builder/chroot/README.md index 91e0e059..d538da4f 100644 --- a/.web-docs/components/builder/chroot/README.md +++ b/.web-docs/components/builder/chroot/README.md @@ -133,7 +133,7 @@ necessary for this build to succeed and can be found further down the page. - `root_device_name` (string) - The root device name. For example, xvda. -- `root_volume_size` (int64) - The size of the root volume in GB for the chroot environment and the +- `root_volume_size` (int32) - The size of the root volume in GB for the chroot environment and the resulting AMI. Default size is the snapshot size of the source_ami unless from_scratch is true, in which case this field must be defined. @@ -259,7 +259,7 @@ builders. [template engine](/packer/docs/templates/legacy_json_templates/engine), see [Build template data](#build-template-data) for more information. -- `ami_virtualization_type` (string) - The type of virtualization for the AMI +- `ami_virtualization_type` (ec2types.VirtualizationType) - The type of virtualization for the AMI you are building. This option is required to register HVM images. Can be paravirtual (default) or hvm. @@ -394,7 +394,7 @@ builders. [Time-based copies]: https://docs.aws.amazon.com/ebs/latest/userguide/time-based-copies.html -- `imds_support` (string) - Enforce version of the Instance Metadata Service on the built AMI. +- `imds_support` (ec2types.ImdsSupportValues) - Enforce version of the Instance Metadata Service on the built AMI. Valid options are unset (legacy) and `v2.0`. See the documentation on [IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for more information. Defaults to legacy. @@ -501,7 +501,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept false will result in an unencrypted device, and true will result in an encrypted one. -- `iops` (\*int64) - The number of I/O operations per second (IOPS) that the volume supports. +- `iops` (\*int32) - The number of I/O operations per second (IOPS) that the volume supports. See the documentation on [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -511,7 +511,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `snapshot_id` (string) - The ID of the snapshot. -- `throughput` (\*int64) - The throughput for gp3 volumes, only valid for gp3 types +- `throughput` (\*int32) - The throughput for gp3 volumes, only valid for gp3 types See the documentation on [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -529,7 +529,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. -- `volume_size` (int64) - The size of the volume, in GiB. Required if not specifying a +- `volume_size` (int32) - The size of the volume, in GiB. Required if not specifying a snapshot_id. - `kms_key_id` (string) - ID, alias or ARN of the KMS key to use for boot volume encryption. @@ -771,6 +771,11 @@ JSON example: 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. +- `max_timeout` (int) - Specifies the maximum timeout in seconds for the waiter. + This value can also be set via the AWS_MAX_TIMEOUT. + If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + diff --git a/.web-docs/components/builder/ebs/README.md b/.web-docs/components/builder/ebs/README.md index 94bb35bf..c5788dc6 100644 --- a/.web-docs/components/builder/ebs/README.md +++ b/.web-docs/components/builder/ebs/README.md @@ -112,7 +112,7 @@ necessary for this build to succeed and can be found further down the page. [template engine](/packer/docs/templates/legacy_json_templates/engine), see [Build template data](#build-template-data) for more information. -- `ami_virtualization_type` (string) - The type of virtualization for the AMI +- `ami_virtualization_type` (ec2types.VirtualizationType) - The type of virtualization for the AMI you are building. This option is required to register HVM images. Can be paravirtual (default) or hvm. @@ -247,7 +247,7 @@ necessary for this build to succeed and can be found further down the page. [Time-based copies]: https://docs.aws.amazon.com/ebs/latest/userguide/time-based-copies.html -- `imds_support` (string) - Enforce version of the Instance Metadata Service on the built AMI. +- `imds_support` (ec2types.ImdsSupportValues) - Enforce version of the Instance Metadata Service on the built AMI. Valid options are unset (legacy) and `v2.0`. See the documentation on [IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for more information. Defaults to legacy. @@ -514,6 +514,11 @@ JSON example: 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. +- `max_timeout` (int) - Specifies the maximum timeout in seconds for the waiter. + This value can also be set via the AWS_MAX_TIMEOUT. + If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + @@ -523,7 +528,7 @@ JSON example: -- `instance_type` (string) - The EC2 instance type to use while building the +- `instance_type` (ec2types.InstanceType) - The EC2 instance type to use while building the AMI, such as t2.small. - `source_ami` (string) - The source AMI whose root volume will be copied and @@ -559,7 +564,7 @@ JSON example: - `availability_zone` (string) - Destination availability zone to launch instance in. Leave this empty to allow Amazon to auto-assign. -- `block_duration_minutes` (int64) - Requires spot_price to be set. The +- `block_duration_minutes` (int32) - Requires spot_price to be set. The required duration for the Spot Instances (also known as Spot blocks). This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360). You can't specify an Availability Zone group or a launch group if you specify a @@ -567,7 +572,7 @@ JSON example: from July 1, 2021. [See Amazon's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances). -- `capacity_reservation_preference` (string) - Set the preference for using a capacity reservation if one exists. +- `capacity_reservation_preference` (ec2types.CapacityReservationPreference) - Set the preference for using a capacity reservation if one exists. Either will be `open` or `none`. Defaults to `none` - `capacity_reservation_id` (string) - Provide the specific EC2 Capacity Reservation ID that will be used @@ -814,7 +819,7 @@ JSON example: criteria provided in `source_ami_filter`; this pins the AMI returned by the filter, but will cause Packer to fail if the `source_ami` does not exist. -- `spot_allocation_strategy` (string) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. +- `spot_allocation_strategy` (ec2types.SpotAllocationStrategy) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. The strategy that determines how to allocate the target Spot Instance capacity across the Spot Instance pools specified by the EC2 Fleet launch configuration. If this option is not set, Packer will use default option provided by the SDK (currently `lowest-price`). @@ -971,7 +976,7 @@ JSON example: Refer to the [Placement docs](#placement-configuration) for more information on the supported attributes for placement configuration. -- `tenancy` (string) - Deprecated: Use Placement Tenancy instead. +- `tenancy` (ec2types.Tenancy) - Deprecated: Use Placement Tenancy instead. - `temporary_security_group_source_cidrs` ([]string) - A list of IPv4/IPv6 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. @@ -1098,7 +1103,7 @@ JSON example: - `host_id` (string) - The ID of the host used when Packer launches an EC2 instance. -- `tenancy` (string) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used +- `tenancy` (ec2types.Tenancy) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware. The default is "default", meaning shared tenancy. Allowed values are "default", @@ -1386,7 +1391,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept false will result in an unencrypted device, and true will result in an encrypted one. -- `iops` (\*int64) - The number of I/O operations per second (IOPS) that the volume supports. +- `iops` (\*int32) - The number of I/O operations per second (IOPS) that the volume supports. See the documentation on [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -1396,7 +1401,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `snapshot_id` (string) - The ID of the snapshot. -- `throughput` (\*int64) - The throughput for gp3 volumes, only valid for gp3 types +- `throughput` (\*int32) - The throughput for gp3 volumes, only valid for gp3 types See the documentation on [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -1414,7 +1419,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. -- `volume_size` (int64) - The size of the volume, in GiB. Required if not specifying a +- `volume_size` (int32) - The size of the volume, in GiB. Required if not specifying a snapshot_id. - `kms_key_id` (string) - ID, alias or ARN of the KMS key to use for boot volume encryption. diff --git a/.web-docs/components/builder/ebssurrogate/README.md b/.web-docs/components/builder/ebssurrogate/README.md index 65458a56..c450d2b9 100644 --- a/.web-docs/components/builder/ebssurrogate/README.md +++ b/.web-docs/components/builder/ebssurrogate/README.md @@ -125,7 +125,7 @@ necessary for this build to succeed and can be found further down the page. [template engine](/packer/docs/templates/legacy_json_templates/engine), see [Build template data](#build-template-data) for more information. -- `ami_virtualization_type` (string) - The type of virtualization for the AMI +- `ami_virtualization_type` (ec2types.VirtualizationType) - The type of virtualization for the AMI you are building. This option is required to register HVM images. Can be paravirtual (default) or hvm. @@ -260,7 +260,7 @@ necessary for this build to succeed and can be found further down the page. [Time-based copies]: https://docs.aws.amazon.com/ebs/latest/userguide/time-based-copies.html -- `imds_support` (string) - Enforce version of the Instance Metadata Service on the built AMI. +- `imds_support` (ec2types.ImdsSupportValues) - Enforce version of the Instance Metadata Service on the built AMI. Valid options are unset (legacy) and `v2.0`. See the documentation on [IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for more information. Defaults to legacy. @@ -527,6 +527,11 @@ JSON example: 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. +- `max_timeout` (int) - Specifies the maximum timeout in seconds for the waiter. + This value can also be set via the AWS_MAX_TIMEOUT. + If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + @@ -536,7 +541,7 @@ JSON example: -- `instance_type` (string) - The EC2 instance type to use while building the +- `instance_type` (ec2types.InstanceType) - The EC2 instance type to use while building the AMI, such as t2.small. - `source_ami` (string) - The source AMI whose root volume will be copied and @@ -572,7 +577,7 @@ JSON example: - `availability_zone` (string) - Destination availability zone to launch instance in. Leave this empty to allow Amazon to auto-assign. -- `block_duration_minutes` (int64) - Requires spot_price to be set. The +- `block_duration_minutes` (int32) - Requires spot_price to be set. The required duration for the Spot Instances (also known as Spot blocks). This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360). You can't specify an Availability Zone group or a launch group if you specify a @@ -580,7 +585,7 @@ JSON example: from July 1, 2021. [See Amazon's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances). -- `capacity_reservation_preference` (string) - Set the preference for using a capacity reservation if one exists. +- `capacity_reservation_preference` (ec2types.CapacityReservationPreference) - Set the preference for using a capacity reservation if one exists. Either will be `open` or `none`. Defaults to `none` - `capacity_reservation_id` (string) - Provide the specific EC2 Capacity Reservation ID that will be used @@ -827,7 +832,7 @@ JSON example: criteria provided in `source_ami_filter`; this pins the AMI returned by the filter, but will cause Packer to fail if the `source_ami` does not exist. -- `spot_allocation_strategy` (string) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. +- `spot_allocation_strategy` (ec2types.SpotAllocationStrategy) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. The strategy that determines how to allocate the target Spot Instance capacity across the Spot Instance pools specified by the EC2 Fleet launch configuration. If this option is not set, Packer will use default option provided by the SDK (currently `lowest-price`). @@ -984,7 +989,7 @@ JSON example: Refer to the [Placement docs](#placement-configuration) for more information on the supported attributes for placement configuration. -- `tenancy` (string) - Deprecated: Use Placement Tenancy instead. +- `tenancy` (ec2types.Tenancy) - Deprecated: Use Placement Tenancy instead. - `temporary_security_group_source_cidrs` ([]string) - A list of IPv4/IPv6 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. @@ -1111,7 +1116,7 @@ JSON example: - `host_id` (string) - The ID of the host used when Packer launches an EC2 instance. -- `tenancy` (string) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used +- `tenancy` (ec2types.Tenancy) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware. The default is "default", meaning shared tenancy. Allowed values are "default", @@ -1388,7 +1393,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept false will result in an unencrypted device, and true will result in an encrypted one. -- `iops` (\*int64) - The number of I/O operations per second (IOPS) that the volume supports. +- `iops` (\*int32) - The number of I/O operations per second (IOPS) that the volume supports. See the documentation on [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -1398,7 +1403,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `snapshot_id` (string) - The ID of the snapshot. -- `throughput` (\*int64) - The throughput for gp3 volumes, only valid for gp3 types +- `throughput` (\*int32) - The throughput for gp3 volumes, only valid for gp3 types See the documentation on [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -1416,7 +1421,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. -- `volume_size` (int64) - The size of the volume, in GiB. Required if not specifying a +- `volume_size` (int32) - The size of the volume, in GiB. Required if not specifying a snapshot_id. - `kms_key_id` (string) - ID, alias or ARN of the KMS key to use for boot volume encryption. diff --git a/.web-docs/components/builder/ebsvolume/README.md b/.web-docs/components/builder/ebsvolume/README.md index b3612e7c..5db05e74 100644 --- a/.web-docs/components/builder/ebsvolume/README.md +++ b/.web-docs/components/builder/ebsvolume/README.md @@ -308,6 +308,11 @@ JSON example: 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. +- `max_timeout` (int) - Specifies the maximum timeout in seconds for the waiter. + This value can also be set via the AWS_MAX_TIMEOUT. + If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + @@ -377,7 +382,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept false will result in an unencrypted device, and true will result in an encrypted one. -- `iops` (\*int64) - The number of I/O operations per second (IOPS) that the volume supports. +- `iops` (\*int32) - The number of I/O operations per second (IOPS) that the volume supports. See the documentation on [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -387,7 +392,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `snapshot_id` (string) - The ID of the snapshot. -- `throughput` (\*int64) - The throughput for gp3 volumes, only valid for gp3 types +- `throughput` (\*int32) - The throughput for gp3 volumes, only valid for gp3 types See the documentation on [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -405,7 +410,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. -- `volume_size` (int64) - The size of the volume, in GiB. Required if not specifying a +- `volume_size` (int32) - The size of the volume, in GiB. Required if not specifying a snapshot_id. - `kms_key_id` (string) - ID, alias or ARN of the KMS key to use for boot volume encryption. @@ -470,7 +475,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept -- `instance_type` (string) - The EC2 instance type to use while building the +- `instance_type` (ec2types.InstanceType) - The EC2 instance type to use while building the AMI, such as t2.small. - `source_ami` (string) - The source AMI whose root volume will be copied and @@ -506,7 +511,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `availability_zone` (string) - Destination availability zone to launch instance in. Leave this empty to allow Amazon to auto-assign. -- `block_duration_minutes` (int64) - Requires spot_price to be set. The +- `block_duration_minutes` (int32) - Requires spot_price to be set. The required duration for the Spot Instances (also known as Spot blocks). This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360). You can't specify an Availability Zone group or a launch group if you specify a @@ -514,7 +519,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept from July 1, 2021. [See Amazon's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances). -- `capacity_reservation_preference` (string) - Set the preference for using a capacity reservation if one exists. +- `capacity_reservation_preference` (ec2types.CapacityReservationPreference) - Set the preference for using a capacity reservation if one exists. Either will be `open` or `none`. Defaults to `none` - `capacity_reservation_id` (string) - Provide the specific EC2 Capacity Reservation ID that will be used @@ -761,7 +766,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept criteria provided in `source_ami_filter`; this pins the AMI returned by the filter, but will cause Packer to fail if the `source_ami` does not exist. -- `spot_allocation_strategy` (string) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. +- `spot_allocation_strategy` (ec2types.SpotAllocationStrategy) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. The strategy that determines how to allocate the target Spot Instance capacity across the Spot Instance pools specified by the EC2 Fleet launch configuration. If this option is not set, Packer will use default option provided by the SDK (currently `lowest-price`). @@ -918,7 +923,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept Refer to the [Placement docs](#placement-configuration) for more information on the supported attributes for placement configuration. -- `tenancy` (string) - Deprecated: Use Placement Tenancy instead. +- `tenancy` (ec2types.Tenancy) - Deprecated: Use Placement Tenancy instead. - `temporary_security_group_source_cidrs` ([]string) - A list of IPv4/IPv6 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. @@ -1045,7 +1050,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `host_id` (string) - The ID of the host used when Packer launches an EC2 instance. -- `tenancy` (string) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used +- `tenancy` (ec2types.Tenancy) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware. The default is "default", meaning shared tenancy. Allowed values are "default", diff --git a/.web-docs/components/builder/instance/README.md b/.web-docs/components/builder/instance/README.md index da9699d4..857df38d 100644 --- a/.web-docs/components/builder/instance/README.md +++ b/.web-docs/components/builder/instance/README.md @@ -103,7 +103,7 @@ necessary for this build to succeed and can be found further down the page. okay to create this directory as part of the provisioning process. Defaults to /tmp. -- `tpm_support` (string) - NitroTPM Support. Valid options are `v2.0`. See the documentation on +- `tpm_support` (ec2types.TpmSupportValues) - NitroTPM Support. Valid options are `v2.0`. See the documentation on [NitroTPM Support](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-support-on-ami.html) for more information. Only enabled if a valid option is provided, otherwise ignored. @@ -133,7 +133,7 @@ necessary for this build to succeed and can be found further down the page. [template engine](/packer/docs/templates/legacy_json_templates/engine), see [Build template data](#build-template-data) for more information. -- `ami_virtualization_type` (string) - The type of virtualization for the AMI +- `ami_virtualization_type` (ec2types.VirtualizationType) - The type of virtualization for the AMI you are building. This option is required to register HVM images. Can be paravirtual (default) or hvm. @@ -268,7 +268,7 @@ necessary for this build to succeed and can be found further down the page. [Time-based copies]: https://docs.aws.amazon.com/ebs/latest/userguide/time-based-copies.html -- `imds_support` (string) - Enforce version of the Instance Metadata Service on the built AMI. +- `imds_support` (ec2types.ImdsSupportValues) - Enforce version of the Instance Metadata Service on the built AMI. Valid options are unset (legacy) and `v2.0`. See the documentation on [IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for more information. Defaults to legacy. @@ -510,6 +510,11 @@ JSON example: 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. +- `max_timeout` (int) - Specifies the maximum timeout in seconds for the waiter. + This value can also be set via the AWS_MAX_TIMEOUT. + If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). + @@ -519,7 +524,7 @@ JSON example: -- `instance_type` (string) - The EC2 instance type to use while building the +- `instance_type` (ec2types.InstanceType) - The EC2 instance type to use while building the AMI, such as t2.small. - `source_ami` (string) - The source AMI whose root volume will be copied and @@ -555,7 +560,7 @@ JSON example: - `availability_zone` (string) - Destination availability zone to launch instance in. Leave this empty to allow Amazon to auto-assign. -- `block_duration_minutes` (int64) - Requires spot_price to be set. The +- `block_duration_minutes` (int32) - Requires spot_price to be set. The required duration for the Spot Instances (also known as Spot blocks). This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360). You can't specify an Availability Zone group or a launch group if you specify a @@ -563,7 +568,7 @@ JSON example: from July 1, 2021. [See Amazon's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances). -- `capacity_reservation_preference` (string) - Set the preference for using a capacity reservation if one exists. +- `capacity_reservation_preference` (ec2types.CapacityReservationPreference) - Set the preference for using a capacity reservation if one exists. Either will be `open` or `none`. Defaults to `none` - `capacity_reservation_id` (string) - Provide the specific EC2 Capacity Reservation ID that will be used @@ -810,7 +815,7 @@ JSON example: criteria provided in `source_ami_filter`; this pins the AMI returned by the filter, but will cause Packer to fail if the `source_ami` does not exist. -- `spot_allocation_strategy` (string) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. +- `spot_allocation_strategy` (ec2types.SpotAllocationStrategy) - One of `price-capacity-optimized`, `capacity-optimized`, `diversified` or `lowest-price`. The strategy that determines how to allocate the target Spot Instance capacity across the Spot Instance pools specified by the EC2 Fleet launch configuration. If this option is not set, Packer will use default option provided by the SDK (currently `lowest-price`). @@ -967,7 +972,7 @@ JSON example: Refer to the [Placement docs](#placement-configuration) for more information on the supported attributes for placement configuration. -- `tenancy` (string) - Deprecated: Use Placement Tenancy instead. +- `tenancy` (ec2types.Tenancy) - Deprecated: Use Placement Tenancy instead. - `temporary_security_group_source_cidrs` ([]string) - A list of IPv4/IPv6 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. @@ -1207,7 +1212,7 @@ The absence of this permission won't prevent you from building the AMI, and the - `host_id` (string) - The ID of the host used when Packer launches an EC2 instance. -- `tenancy` (string) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used +- `tenancy` (ec2types.Tenancy) - [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware. The default is "default", meaning shared tenancy. Allowed values are "default", @@ -1283,7 +1288,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept false will result in an unencrypted device, and true will result in an encrypted one. -- `iops` (\*int64) - The number of I/O operations per second (IOPS) that the volume supports. +- `iops` (\*int32) - The number of I/O operations per second (IOPS) that the volume supports. See the documentation on [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -1293,7 +1298,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept - `snapshot_id` (string) - The ID of the snapshot. -- `throughput` (\*int64) - The throughput for gp3 volumes, only valid for gp3 types +- `throughput` (\*int32) - The throughput for gp3 volumes, only valid for gp3 types See the documentation on [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html) for more information @@ -1311,7 +1316,7 @@ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concept for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1 for Cold HDD, and standard for Magnetic volumes. -- `volume_size` (int64) - The size of the volume, in GiB. Required if not specifying a +- `volume_size` (int32) - The size of the volume, in GiB. Required if not specifying a snapshot_id. - `kms_key_id` (string) - ID, alias or ARN of the KMS key to use for boot volume encryption. From efe7dcab8fab3b2f7d2712fc4dbad6212ed7bec8 Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Tue, 19 May 2026 14:30:24 +0200 Subject: [PATCH 6/8] fix: Update the libraries after sync from main --- go.mod | 16 ++++++++-------- go.sum | 44 ++++++++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index f811e28e..153e5f71 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/hcl/v2 v2.24.0 - github.com/hashicorp/packer-plugin-sdk v0.6.7 + github.com/hashicorp/packer-plugin-sdk v0.6.8 github.com/hashicorp/vault/api v1.23.0 github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.11.1 @@ -36,7 +36,7 @@ require ( cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.11.0 // indirect cloud.google.com/go/monitoring v1.29.0 // indirect - cloud.google.com/go/storage v1.62.1 // indirect + cloud.google.com/go/storage v1.62.2 // indirect github.com/Azure/go-ntlmssp v0.1.1 // indirect github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect @@ -102,7 +102,7 @@ require ( require ( github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.17 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.301.0 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.303.0 github.com/aws/smithy-go v1.25.1 github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -165,11 +165,11 @@ require ( golang.org/x/term v0.43.0 // indirect golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.15.0 // indirect - google.golang.org/api v0.278.0 // indirect - google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 // indirect - google.golang.org/grpc v1.81.0 // indirect + google.golang.org/api v0.279.0 // indirect + google.golang.org/genproto v0.0.0-20260519071638-aa98bba5eb94 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260519071638-aa98bba5eb94 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260519071638-aa98bba5eb94 // indirect + google.golang.org/grpc v1.81.1 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1f0890ea..a20589fc 100644 --- a/go.sum +++ b/go.sum @@ -11,16 +11,16 @@ cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdB cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/iam v1.11.0 h1:KieQ9Pb+LLPak1O3Rv3GgCxhnmkYf7Xyh0P5HfF1jFM= cloud.google.com/go/iam v1.11.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= -cloud.google.com/go/logging v1.17.0 h1:rUFekZYwHiKElXCyz3zYBGz4BOeIqzgCKxVLdgrZ5mY= -cloud.google.com/go/logging v1.17.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= -cloud.google.com/go/longrunning v0.12.0 h1:wLv2hXvID9zHejLtcPo1B0JBjErnwZCYAPKSTa65xpY= -cloud.google.com/go/longrunning v0.12.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= +cloud.google.com/go/logging v1.18.0 h1:KhzZq+1cSkPH9YUaKLLhLtQxIHitVayBmk0sGfoM9+k= +cloud.google.com/go/logging v1.18.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= +cloud.google.com/go/longrunning v1.0.0 h1:lwzWEYD8+NkYV7dhexOz6kmlvajZA70+bW/xMhRVVdY= +cloud.google.com/go/longrunning v1.0.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= cloud.google.com/go/monitoring v1.29.0 h1:AHhDsFaSax1/4k+qlIDX/SDGe6hggnfXJ9dkgD9qBPY= cloud.google.com/go/monitoring v1.29.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= -cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= -cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= -cloud.google.com/go/trace v1.15.0 h1:kAYkTwKyYHkGtAGFuu6qaUFRBkOVr+d1Yo44yZtGtgg= -cloud.google.com/go/trace v1.15.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= +cloud.google.com/go/storage v1.62.2 h1:WgR4U9n7bIzXkkVnwPKKE8bkaKUNsHG+0MAAlh9DGU4= +cloud.google.com/go/storage v1.62.2/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cloud.google.com/go/trace v1.16.0 h1:GmQovzFc5F0CNfl0VLgL64aoTtu7xsM0YajW2GlG9+E= +cloud.google.com/go/trace v1.16.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw= github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk= github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 h1:w0E0fgc1YafGEh5cROhlROMWXiNoZqApk2PDN0M1+Ns= @@ -73,8 +73,8 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3 h1:XgjzLEE8CrNYnr4Xmi1W5PfKsKMjp4Pu1rWkJNO43JI= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3/go.mod h1:r7sfLXEN8RUA89tAHy1E7lCtVOOWIkqVy/FbnUdxW1E= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.301.0 h1:U+cZAMc8mN0jne8/ae7KrrFuILTXrZReAvc6BIpXGls= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.301.0/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.303.0 h1:qkTLlFVQDSk0tbOqn49pxZjIVY2jy3n0FBXh+PphNkk= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.303.0/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY= github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.32.22 h1:wc+/Ueo9HO1HbQGoYzjoozB3Zk4hJ67ykgyZC5yMEJ8= github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect v1.32.22/go.mod h1:yzDJW0Xp6ZPFise7iBYVjuRhAva8b7u9rYoVnE+xPi4= github.com/aws/aws-sdk-go-v2/service/iam v1.53.10 h1:kcN3I3llO7VwIY5w3Pc5FmEonpsr23Ou7Cwk4qf7dik= @@ -271,8 +271,8 @@ github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQx github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/hashicorp/memberlist v0.5.2 h1:rJoNPWZ0juJBgqn48gjy59K5H4rNgvUoM1kUD7bXiuI= github.com/hashicorp/memberlist v0.5.2/go.mod h1:Ri9p/tRShbjYnpNf4FFPXG7wxEGY4Nrcn6E7jrVa//4= -github.com/hashicorp/packer-plugin-sdk v0.6.7 h1:R6xO8j5GUT1AC+1CmDvXCjjiCDndWbIA1O7jJ3MeTVs= -github.com/hashicorp/packer-plugin-sdk v0.6.7/go.mod h1:J+hZE+SdN0MPCZLmoRPSrqg4YuP/mXTuuVqiAYbDVfw= +github.com/hashicorp/packer-plugin-sdk v0.6.8 h1:uBINKQOqcxb9ERgWm16Rdbcxj91Iyq2g1RVCuUsEN7I= +github.com/hashicorp/packer-plugin-sdk v0.6.8/go.mod h1:TvwlqryoWOljacuCtF5SKOg3Kz2sgydRVJzqY/S3PkY= github.com/hashicorp/serf v0.10.2 h1:m5IORhuNSjaxeljg5DeQVDlQyVkhRIjJDimbkCa8aAc= github.com/hashicorp/serf v0.10.2/go.mod h1:T1CmSGfSeGfnfNy/w0odXQUR1rfECGd2Qdsp84DjOiY= github.com/hashicorp/terraform-plugin-log v0.10.0 h1:eu2kW6/QBVdN4P3Ju2WiB2W3ObjkAsyfBsL3Wh1fj3g= @@ -537,17 +537,17 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.278.0 h1:W7jiRvRi53VYFfZ/HoZjQBtJk7gOFbHD8ot1RzVZU6E= -google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= +google.golang.org/api v0.279.0 h1:hsx2M2OaRcaKtVYK6vXEUnQvdjnend7ZYES+lYaot74= +google.golang.org/api v0.279.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348 h1:JjVGDZYWkJWZcxveJGzfkXC5myDVWAd4dZdgbzrDUv8= -google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348/go.mod h1:95PqD4xM+AdOcBGsmgfaofXsiA37uXDtDufVbntT3TU= -google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 h1:U8orV30l6KpDsi9dxU0CoJZGbjS8EEpw+6ba+XwGPQA= -google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348/go.mod h1:Yzdzr5OOZFgSsEV2D/Xi9NL3bszpXFAg0hFJiRohcD8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 h1:pfIbyB44sWzHiCpRqIen67ZQnVXSfIxWrqUMk1qwODE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= -google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/genproto v0.0.0-20260519071638-aa98bba5eb94 h1:YJjbgu+dkp5kUJLfpMyCLfBIWZb/FcJyuLeo1gVBOuo= +google.golang.org/genproto v0.0.0-20260519071638-aa98bba5eb94/go.mod h1:RRHjglSYABVCWpQ7USCpdfhcd9t4PkajvVwyynZizTc= +google.golang.org/genproto/googleapis/api v0.0.0-20260519071638-aa98bba5eb94 h1:DddG61lE5LkX6144z22i0gma9BMBs5aZ9B8lZLobxyw= +google.golang.org/genproto/googleapis/api v0.0.0-20260519071638-aa98bba5eb94/go.mod h1:1dCETSCY2YKZNXQE3h4fun3TYwF5p8jejRKZgfWAgAY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260519071638-aa98bba5eb94 h1:eZCjr/aAF8c5ccm5pb6T4EXgIei5MlAAPWPJk+5ArfY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260519071638-aa98bba5eb94/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From b7f5dd9b79b2baf70a12419631b479da47d82b10 Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Tue, 19 May 2026 14:50:50 +0200 Subject: [PATCH 7/8] fix: Fixes from Copilot review --- builder/common/access_config.go | 3 ++- builder/common/step_iam_instance_profile.go | 4 ++-- builder/common/step_key_pair.go | 5 ++--- builder/common/step_key_pair_test.go | 3 +-- builder/common/step_stop_ebs_instance.go | 4 ++-- builder/ebs/step_create_ami.go | 2 +- builder/ebssurrogate/step_create_ami.go | 2 +- builder/ebssurrogate/step_snapshot_volumes.go | 2 +- builder/ebssurrogate/step_swap_volumes.go | 4 ++-- builder/ebsvolume/step_tag_ebs_volumes.go | 2 +- builder/instance/step_upload_bundle.go | 6 ++++++ common/step_create_ssm_tunnel.go | 6 +++--- common/step_get_password.go | 2 +- common/step_modify_ebs_instance.go | 2 +- common/step_stop_ebs_instance.go | 2 +- 15 files changed, 27 insertions(+), 22 deletions(-) diff --git a/builder/common/access_config.go b/builder/common/access_config.go index d37e7918..a34913f6 100644 --- a/builder/common/access_config.go +++ b/builder/common/access_config.go @@ -254,7 +254,8 @@ func (c *AccessConfig) GetAWSConfig(ctx context.Context) (*aws.Config, error) { } } - return &awsConfig, nil + c.awsConfig = &awsConfig + return c.awsConfig, nil } func (c *AccessConfig) SessionRegion() string { diff --git a/builder/common/step_iam_instance_profile.go b/builder/common/step_iam_instance_profile.go index 8017466c..7d267a2c 100644 --- a/builder/common/step_iam_instance_profile.go +++ b/builder/common/step_iam_instance_profile.go @@ -70,8 +70,8 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB ui.Say(fmt.Sprintf("Creating temporary instance profile for this instance: %s", profileName)) - region := state.Get("region").(*string) - iamProfileTags, err := TagMap(s.Tags).IamTags(s.Ctx, *region, state) + region := state.Get("region").(string) + iamProfileTags, err := TagMap(s.Tags).IamTags(s.Ctx, region, state) if err != nil { err := fmt.Errorf("Error creating IAM tags: %s", err) state.Put("error", err) diff --git a/builder/common/step_key_pair.go b/builder/common/step_key_pair.go index 61aea651..64e0a833 100644 --- a/builder/common/step_key_pair.go +++ b/builder/common/step_key_pair.go @@ -10,7 +10,6 @@ import ( "runtime" "time" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" @@ -74,8 +73,8 @@ func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multist } if !s.IsRestricted { - region := state.Get("region").(*string) - ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, aws.ToString(region), state) + region := state.Get("region").(string) + ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, region, state) if err != nil { err := fmt.Errorf("Error tagging key pair: %s", err) state.Put("error", err) diff --git a/builder/common/step_key_pair_test.go b/builder/common/step_key_pair_test.go index cab2c65c..05e01a6d 100644 --- a/builder/common/step_key_pair_test.go +++ b/builder/common/step_key_pair_test.go @@ -9,7 +9,6 @@ import ( "sync" "testing" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/packer-plugin-amazon/common/clients" @@ -51,7 +50,7 @@ func keyPairState() multistep.StateBag { }) conn := getKeyPairMockConn() state.Put("ec2", conn) - state.Put("region", aws.String("us-east-1")) + state.Put("region", "us-east-1") return state } diff --git a/builder/common/step_stop_ebs_instance.go b/builder/common/step_stop_ebs_instance.go index 52207f50..91d5bd7c 100644 --- a/builder/common/step_stop_ebs_instance.go +++ b/builder/common/step_stop_ebs_instance.go @@ -48,7 +48,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta // does not exist. // Work around this by retrying a few times, up to about 5 minutes. - err := retry.Config{Tries: 6, ShouldRetry: func(error) bool { + err := retry.Config{Tries: 6, ShouldRetry: func(err error) bool { if awserrors.Matches(err, "InvalidInstanceID.NotFound", "") { return true } @@ -81,7 +81,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta w := ec2.NewInstanceStoppedWaiter(ec2conn) err = w.Wait(ctx, &ec2.DescribeInstancesInput{ InstanceIds: []string{aws.ToString(instance.InstanceId)}, - }, time.Duration(s.PollingConfig.MaxTimeout)) + }, time.Duration(s.PollingConfig.MaxTimeout)*time.Second) if err != nil { err := fmt.Errorf("Error waiting for instance to stop: %s", err) state.Put("error", err) diff --git a/builder/ebs/step_create_ami.go b/builder/ebs/step_create_ami.go index 7fb7584f..4e84cdf1 100644 --- a/builder/ebs/step_create_ami.go +++ b/builder/ebs/step_create_ami.go @@ -37,7 +37,7 @@ func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi config := state.Get("config").(*Config) ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) if s.AMISkipCreateImage { diff --git a/builder/ebssurrogate/step_create_ami.go b/builder/ebssurrogate/step_create_ami.go index b8f12840..1981a92b 100644 --- a/builder/ebssurrogate/step_create_ami.go +++ b/builder/ebssurrogate/step_create_ami.go @@ -40,7 +40,7 @@ func (s *StepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi config := state.Get("config").(*Config) ec2Client := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) blockDevices := s.combineDevices() diff --git a/builder/ebssurrogate/step_snapshot_volumes.go b/builder/ebssurrogate/step_snapshot_volumes.go index a8be3345..f62f6149 100644 --- a/builder/ebssurrogate/step_snapshot_volumes.go +++ b/builder/ebssurrogate/step_snapshot_volumes.go @@ -40,7 +40,7 @@ func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName str ec2conn := state.Get("ec2").(clients.Ec2Client) awsConfig := state.Get("aws_config").(*aws.Config) ui := state.Get("ui").(packersdk.Ui) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) var volumeId string for _, volume := range instance.BlockDeviceMappings { diff --git a/builder/ebssurrogate/step_swap_volumes.go b/builder/ebssurrogate/step_swap_volumes.go index a1d1d143..5d4e5bec 100644 --- a/builder/ebssurrogate/step_swap_volumes.go +++ b/builder/ebssurrogate/step_swap_volumes.go @@ -31,7 +31,7 @@ type StepSwapVolumes struct { func (s *StepSwapVolumes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) // Describe the instance input := &ec2.DescribeInstancesInput{ @@ -145,7 +145,7 @@ func (s *StepSwapVolumes) Cleanup(state multistep.StateBag) { ctx := context.TODO() ec2Client := state.Get("ec2").(clients.Ec2Client) ui := state.Get("ui").(packersdk.Ui) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui.Say("Cleaning up any detached volumes with delete_on_termination set to true...") // Describe the instance input := &ec2.DescribeInstancesInput{ diff --git a/builder/ebsvolume/step_tag_ebs_volumes.go b/builder/ebsvolume/step_tag_ebs_volumes.go index 8485b6f7..e1de7902 100644 --- a/builder/ebsvolume/step_tag_ebs_volumes.go +++ b/builder/ebsvolume/step_tag_ebs_volumes.go @@ -25,7 +25,7 @@ type stepTagEBSVolumes struct { func (s *stepTagEBSVolumes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ec2Client := state.Get("ec2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) region := state.Get("region").(string) ui := state.Get("ui").(packersdk.Ui) config := state.Get("config").(*Config) diff --git a/builder/instance/step_upload_bundle.go b/builder/instance/step_upload_bundle.go index 1dfc26bb..b19731dc 100644 --- a/builder/instance/step_upload_bundle.go +++ b/builder/instance/step_upload_bundle.go @@ -36,6 +36,12 @@ func (s *StepUploadBundle) Run(ctx context.Context, state multistep.StateBag) mu accessKey := config.AccessKey secretKey := config.SecretKey awscfg, err := config.AccessConfig.GetAWSConfig(ctx) + if err != nil { + err = fmt.Errorf("Error creating AWS config: %w", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } region := awscfg.Region var token string if err == nil && accessKey == "" && secretKey == "" { diff --git a/common/step_create_ssm_tunnel.go b/common/step_create_ssm_tunnel.go index 4c658eae..5049adfd 100644 --- a/common/step_create_ssm_tunnel.go +++ b/common/step_create_ssm_tunnel.go @@ -64,7 +64,7 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) } // Get instance information - instance, ok := state.Get("instance").(ec2types.Instance) + instance, ok := state.Get("instance").(*ec2types.Instance) if !ok { err := fmt.Errorf("error encountered in obtaining target instance id for session tunnel") ui.Error(err.Error()) @@ -93,7 +93,7 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) } func (s *StepCreateSSMTunnel) CreatePersistentSSMSession(ctx context.Context, ui packersdk.Ui, session *pssm.Session, - instance ec2types.Instance) { + instance *ec2types.Instance) { sessionChan := make(chan struct{}) go func() { @@ -118,7 +118,7 @@ func (s *StepCreateSSMTunnel) CreatePersistentSSMSession(ctx context.Context, ui func (s *StepCreateSSMTunnel) sendUserSSHPublicKey( ctx context.Context, - instance ec2types.Instance, + instance *ec2types.Instance, privateKey []byte, ) error { publicKey, err := sshkey.PublicKeyFromPrivate(privateKey) diff --git a/common/step_get_password.go b/common/step_get_password.go index 78d7a6d2..d034b3ae 100644 --- a/common/step_get_password.go +++ b/common/step_get_password.go @@ -105,7 +105,7 @@ func (s *StepGetPassword) Cleanup(multistep.StateBag) {} func (s *StepGetPassword) waitForPassword(ctx context.Context, state multistep.StateBag) (string, error) { ec2Client := state.Get("ec2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) privateKey := s.Comm.SSHPrivateKey for { diff --git a/common/step_modify_ebs_instance.go b/common/step_modify_ebs_instance.go index b9d885a5..11b48803 100644 --- a/common/step_modify_ebs_instance.go +++ b/common/step_modify_ebs_instance.go @@ -24,7 +24,7 @@ type StepModifyEBSBackedInstance struct { func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ec2Client := state.Get("ec2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) // Skip when it is a spot instance diff --git a/common/step_stop_ebs_instance.go b/common/step_stop_ebs_instance.go index 883176ce..5dd7cce4 100644 --- a/common/step_stop_ebs_instance.go +++ b/common/step_stop_ebs_instance.go @@ -26,7 +26,7 @@ type StepStopEBSBackedInstance struct { func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ec2Client := state.Get("ec2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) // Skip when it is a spot instance From 88201d03c84a419cf4e84ee0aa5afdda669413d3 Mon Sep 17 00:00:00 2001 From: Karel Pazdera Date: Tue, 19 May 2026 15:13:24 +0200 Subject: [PATCH 8/8] fix: Fix the issues from Copilot review --- builder/chroot/builder.go | 1 + builder/common/state.go | 4 ++-- builder/common/step_ami_region_copy.go | 4 ++-- builder/common/step_set_generated_data.go | 6 +++--- builder/instance/builder.go | 1 + 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/builder/chroot/builder.go b/builder/chroot/builder.go index c32792ff..d54d960b 100644 --- a/builder/chroot/builder.go +++ b/builder/chroot/builder.go @@ -431,6 +431,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) // Setup the state bag and initial state for the steps state := new(multistep.BasicStateBag) + state.Put("ctx", ctx) state.Put("config", &b.config) state.Put("access_config", &b.config.AccessConfig) state.Put("ami_config", &b.config.AMIConfig) diff --git a/builder/common/state.go b/builder/common/state.go index 1e605ddd..679677c1 100644 --- a/builder/common/state.go +++ b/builder/common/state.go @@ -83,8 +83,8 @@ type AWSPollingConfig struct { // If none is set, defaults to AWS waiter default which is 15 seconds. DelaySeconds int `mapstructure:"delay_seconds" required:"false"` // Specifies the maximum timeout in seconds for the waiter. - // This value can also be set via the AWS_MAX_TIMEOUT. - // If both option and environment variable are set, the max_timeout will be considered over the AWS_MAX_TIMEOUT. + // This value can also be set via the AWS_TIMEOUT_SECONDS. + // If both option and environment variable are set, the max_timeout will be considered over the AWS_TIMEOUT_SECONDS. // If none is set, defaults to AWS waiter default which is 600 seconds (10 minutes). MaxTimeout int `mapstructure:"max_timeout" required:"false"` } diff --git a/builder/common/step_ami_region_copy.go b/builder/common/step_ami_region_copy.go index fb7c52ea..7bf804b4 100644 --- a/builder/common/step_ami_region_copy.go +++ b/builder/common/step_ami_region_copy.go @@ -192,7 +192,7 @@ func GetEc2Client(ctx context.Context, config *AccessConfig, target string) (cli return client, nil } -func (s *StepAMIRegionCopy) copyImageV2(ctx context.Context, regionconn clients.Ec2Client, name, imageId, target, source, +func (s *StepAMIRegionCopy) copyImage(ctx context.Context, regionconn clients.Ec2Client, name, imageId, target, source, keyId string, encrypt *bool, amiSnapshotCopyDurationMinutes int64) (string, error) { var amiImageId string @@ -241,7 +241,7 @@ func (s *StepAMIRegionCopy) amiRegionCopy(ctx context.Context, state multistep.S return "", snapshotIds, fmt.Errorf("error getting EC2 client for region (%s): %w", target, err) } - amiImageId, err = s.copyImageV2(ctx, regionconn, name, imageId, target, source, keyId, encrypt, s.AMISnapshotCopyDurationMinutes) + amiImageId, err = s.copyImage(ctx, regionconn, name, imageId, target, source, keyId, encrypt, s.AMISnapshotCopyDurationMinutes) if err != nil { return "", snapshotIds, fmt.Errorf("error copying AMI (%s) to region (%s): %w", imageId, target, err) } diff --git a/builder/common/step_set_generated_data.go b/builder/common/step_set_generated_data.go index 82e525ff..a7e824a7 100644 --- a/builder/common/step_set_generated_data.go +++ b/builder/common/step_set_generated_data.go @@ -6,7 +6,7 @@ package common import ( "context" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata" ) @@ -20,9 +20,9 @@ type StepSetGeneratedData struct { } func (s *StepSetGeneratedData) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + awscfg := state.Get("awsConfig").(*aws.Config) - extractBuildInfo(*ec2conn.Config.Region, state, s.GeneratedData) + extractBuildInfo(awscfg.Region, state, s.GeneratedData) return multistep.ActionContinue } diff --git a/builder/instance/builder.go b/builder/instance/builder.go index 0ad6a79e..7cdea3b4 100644 --- a/builder/instance/builder.go +++ b/builder/instance/builder.go @@ -264,6 +264,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) // Setup the state bag and initial state for the steps state := new(multistep.BasicStateBag) + state.Put("ctx", ctx) state.Put("config", &b.config) state.Put("access_config", &b.config.AccessConfig) state.Put("ami_config", &b.config.AMIConfig)