diff --git a/.github/workflows/go-validate.yml b/.github/workflows/go-validate.yml index c996df468..5a8d8af7b 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/.go-version b/.go-version index 7ae54502c..958bb4d76 100644 --- a/.go-version +++ b/.go-version @@ -1,2 +1,2 @@ -1.24.0 +1.26.0 diff --git a/.web-docs/components/builder/chroot/README.md b/.web-docs/components/builder/chroot/README.md index 91e0e059d..d538da4f2 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 94bb35bf3..c5788dc60 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 65458a56e..c450d2b9e 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 b3612e7c8..5db05e749 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 da9699d46..857df38da 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. diff --git a/builder/chroot/builder.go b/builder/chroot/builder.go index 66772f502..d54d960bf 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,7 +113,7 @@ 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 @@ -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 != string(ec2types.TpmSupportValuesV20) { + errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`The only valid tpm_support value is %q`, ec2types.TpmSupportValuesV20)) } if b.config.BootMode != "" { @@ -394,7 +395,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { if b.config.UefiData != "" { 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 != "arm64" { + } 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)) } @@ -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 @@ -430,11 +431,12 @@ 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) 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)) @@ -469,7 +471,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, @@ -518,9 +520,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, @@ -529,7 +531,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 +580,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/builder.hcl2spec.go b/builder/chroot/builder.hcl2spec.go index 19f505bc0..cf8168fd4 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,7 +78,7 @@ 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"` + RootVolumeSize *int32 `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"` 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"` diff --git a/builder/chroot/step_attach_volume.go b/builder/chroot/step_attach_volume.go index ab2e5e3f1..566d9c973 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,6 +65,7 @@ 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 } @@ -80,11 +82,12 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error { return nil } - ec2conn := state.Get("ec2").(*ec2.EC2) + 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(&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 b1aa2c23e..f6e66395b 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 f18285c74..2317d71c4 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 b56fcaf18..7b5aefa1a 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.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 a782c53a4..7c705045a 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) @@ -55,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_mount_device.go b/builder/chroot/step_mount_device.go index b13fa054c..c82ddb31e 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 597d1b8f4..cbfbd5c6b 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: ec2types.ArchitectureValues(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 96d94012f..e4b01c207 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 3bbd3abc8..bfa099cf1 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 fe44026c1..a34913f6a 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{} + var 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() { @@ -265,113 +254,15 @@ 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 + c.awsConfig = &awsConfig + return c.awsConfig, 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 +273,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{}{ @@ -505,6 +356,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. @@ -529,16 +381,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 8ac2af11c..f3566a73f 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 c90bc1591..7e29baece 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 3e70289de..780207184 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 77e85bd15..a52db3a58 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 6ef433cb6..7a8b0cece 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 be70a230d..c52869116 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. @@ -107,7 +107,7 @@ type BlockDevice struct { VolumeType string `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 = ec2types.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": + 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 == "gp3" { + if ec2types.VolumeType(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 { @@ -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 5f5c3f062..3b7dd2a54 100644 --- a/builder/common/block_device.hcl2spec.go +++ b/builder/common/block_device.hcl2spec.go @@ -13,13 +13,13 @@ 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"` + 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 *int64 `mapstructure:"throughput" required:"false" cty:"throughput" hcl:"throughput"` + 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 *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"` + 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"` } diff --git a/builder/common/block_device_test.go b/builder/common/block_device_test.go index 713acac69..f75262e01 100644 --- a/builder/common/block_device_test.go +++ b/builder/common/block_device_test.go @@ -6,9 +6,10 @@ 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/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" ) @@ -16,23 +17,23 @@ import ( func TestBlockDevice(t *testing.T) { cases := []struct { Config *BlockDevice - Result *ec2.BlockDeviceMapping + Result ec2types.BlockDeviceMapping }{ { Config: &BlockDevice{ DeviceName: "/dev/sdb", SnapshotId: "snap-1234", - VolumeType: "standard", + VolumeType: string(ec2types.VolumeTypeStandard), VolumeSize: 8, 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 +44,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), }, }, @@ -54,55 +55,55 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), 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), }, }, }, { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), 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), }, }, }, { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp2", + VolumeType: string(ec2types.VolumeTypeGp2), VolumeSize: 8, DeleteOnTermination: true, 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), }, @@ -111,18 +112,18 @@ 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: &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"), @@ -132,14 +133,14 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "standard", + VolumeType: string(ec2types.VolumeTypeStandard), 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 +151,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 +162,7 @@ func TestBlockDevice(t *testing.T) { NoDevice: true, }, - Result: &ec2.BlockDeviceMapping{ + Result: ec2types.BlockDeviceMapping{ DeviceName: aws.String("/dev/sdb"), NoDevice: aws.String(""), }, @@ -169,21 +170,21 @@ func TestBlockDevice(t *testing.T) { { Config: &BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", + VolumeType: string(ec2types.VolumeTypeGp3), 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,20 +197,28 @@ 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 != "" { + 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,16 +230,16 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", - IOPS: aws.Int64(1000), + VolumeType: string(ec2types.VolumeTypeIo1), + IOPS: aws.Int32(1000), }, ok: true, }, { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", - IOPS: aws.Int64(1000), + VolumeType: string(ec2types.VolumeTypeIo2), + IOPS: aws.Int32(1000), }, ok: true, }, @@ -238,18 +247,18 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), VolumeSize: 50, - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, ok: true, }, { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 100, - IOPS: aws.Int64(1000), + IOPS: aws.Int32(1000), }, ok: true, }, @@ -257,9 +266,9 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io1", + VolumeType: string(ec2types.VolumeTypeIo1), 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", @@ -267,9 +276,9 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), 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", @@ -278,9 +287,9 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 500, - IOPS: aws.Int64(99999), + IOPS: aws.Int32(99999), }, ok: false, msg: "IOPS must be between 100 and 64000 for device /dev/sdb", @@ -289,9 +298,9 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "io2", + VolumeType: string(ec2types.VolumeTypeIo2), VolumeSize: 50, - IOPS: aws.Int64(10), + IOPS: aws.Int32(10), }, ok: false, msg: "IOPS must be between 100 and 64000 for device /dev/sdb", @@ -300,10 +309,10 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", + VolumeType: string(ec2types.VolumeTypeGp3), 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", @@ -312,10 +321,10 @@ func TestIOPSValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", + VolumeType: string(ec2types.VolumeTypeGp3), 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 +357,18 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(125), - IOPS: aws.Int64(3000), + VolumeType: string(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: string(ec2types.VolumeTypeGp3), + Throughput: aws.Int32(1000), + IOPS: aws.Int32(3000), }, ok: true, }, @@ -367,9 +376,9 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(1001), - IOPS: aws.Int64(3000), + VolumeType: string(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 +387,9 @@ func TestThroughputValidation(t *testing.T) { { device: BlockDevice{ DeviceName: "/dev/sdb", - VolumeType: "gp3", - Throughput: aws.Int64(124), - IOPS: aws.Int64(3000), + VolumeType: string(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 cbc028d54..be43cfdfd 100644 --- a/builder/common/boot_mode_validation.go +++ b/builder/common/boot_mode_validation.go @@ -3,14 +3,18 @@ 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"} + 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 0cc4184f5..6321596a6 100644 --- a/builder/common/boot_mode_validation_test.go +++ b/builder/common/boot_mode_validation_test.go @@ -3,7 +3,9 @@ package common -import "testing" +import ( + "testing" +) func TestIsValidBuildMode(t *testing.T) { tests := []struct { diff --git a/builder/common/build_filter.go b/builder/common/build_filter.go index 068693bb4..2828b6449 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 502d9fbaf..2903843e8 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 ff3ea5d52..b1a1c7eaf 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, }) @@ -28,8 +29,6 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { // Deregister image by name. for _, i := range resp.Images { - - ctx := context.TODO() err = retry.Config{ Tries: 11, ShouldRetry: func(err error) bool { @@ -37,7 +36,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 +50,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 +59,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 a07bf6023..9c6250dd6 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/interpolate_build_info_test.go b/builder/common/interpolate_build_info_test.go index d44f1545e..aa04c06e7 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/regions.go b/builder/common/regions.go index f773420e3..79115e7be 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 16dc8cf82..6b79542dd 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". @@ -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.hcl2spec.go b/builder/common/run_config.hcl2spec.go index 565b2d671..340efe1bd 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/run_config_test.go b/builder/common/run_config_test.go index d6bf938cd..bf68ccbfa 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/snapshot_config.go b/builder/common/snapshot_config.go index fc34c6195..1d2ad9153 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/ssh.go b/builder/common/ssh.go index 3aa3789ee..fa89a5094 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 @@ -91,7 +97,7 @@ func SSHHost(e ec2Describer, sshInterface string, host string) func(multistep.St 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/ssh_test.go b/builder/common/ssh_test.go index 85c2d6e0c..7f243035c 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 0411d4cb7..21852c84e 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 c95526d5a..679677c19 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,23 +82,21 @@ 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_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"` } -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() - 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)) - } - err := conn.WaitUntilImageAvailableWithContext( - ctx, - &imageInput, - waitOpts...) + waiter := ec2.NewImageAvailableWaiter(conn) + 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 "+ @@ -106,269 +110,663 @@ 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() - 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)) - } - - err := conn.WaitUntilSnapshotCompletedWithContext( - ctx, - &snapInput, - waitOpts...) + maxTimeout := w.WithMaxAttempts(120).MaxTimeout + waiter := ec2.NewSnapshotCompletedWaiter(conn) + err := waiter.Wait(ctx, &snapInput, time.Duration(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 @@ -401,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 { + if envOverrides.awsPollDelaySeconds.overridden { + w.DelaySeconds = envOverrides.awsPollDelaySeconds.Val + } else { + w.DelaySeconds = 15 + } } - if w.DelaySeconds != 0 { - envOverrides.awsPollDelaySeconds.Val = w.DelaySeconds - envOverrides.awsPollDelaySeconds.overridden = true + 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 { @@ -506,3 +925,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/state.hcl2spec.go b/builder/common/state.hcl2spec.go index 30a21bd1d..055d3e6bc 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_ami_region_copy.go b/builder/common/step_ami_region_copy.go index 98a0a70a8..7bf804b4f 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) copyImage(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,25 @@ 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 + 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) } - regionconn, err := s.getRegionConn(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.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) } // Wait for the image to become ready @@ -293,7 +253,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 473bff8e8..fe4fb2d22 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,21 @@ 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{ec2types.Image{ + ImageId: aws.String("ami-12345"), + State: ec2types.ImageStateAvailable, + RootDeviceName: aws.String("/dev/sda1"), + }}, } 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 +71,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 +79,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 +111,8 @@ 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") + accessConfig := FakeAccessConfig() + conn, _ := getMockConn(ctx, accessConfig, "us-east-2") state.Put("ec2", conn) return state } @@ -123,9 +136,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 +159,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 +181,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 +207,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 +232,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 +254,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 +281,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 +308,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 +337,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 +365,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 +391,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 +417,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_cleanup_volumes.go b/builder/common/step_cleanup_volumes.go index ec83ce8fa..3b281c289 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_create_ssm_tunnel.go b/builder/common/step_create_ssm_tunnel.go index 5bec885d2..da15475dc 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 e705ce124..0ab880547 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 e63e37ef3..45b4b1cb1 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 b40d6e818..deda3cba9 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 := 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 033173327..8744b1af2 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_get_password.go b/builder/common/step_get_password.go index 17322d5a5..47698a3d1 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_iam_instance_profile.go b/builder/common/step_iam_instance_profile.go index 5c08f89fe..7d267a2cd 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) @@ -68,14 +70,14 @@ 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) 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 d02f95758..64e0a8331 100644 --- a/builder/common/step_key_pair.go +++ b/builder/common/step_key_pair.go @@ -10,9 +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/service/ec2/ec2iface" + "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" @@ -63,18 +63,18 @@ 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)) 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) + 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) @@ -82,7 +82,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 +90,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 +139,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 e3efe488f..05e01a6d6 100644 --- a/builder/common/step_key_pair_test.go +++ b/builder/common/step_key_pair_test.go @@ -9,16 +9,16 @@ import ( "sync" "testing" - "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/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" ) type mockEC2KeyPairConn struct { - ec2iface.EC2API + clients.Ec2Client CreateKeyPairCount int CreateKeyPairArgs []ec2.CreateKeyPairInput @@ -26,7 +26,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) @@ -38,7 +38,7 @@ func (m *mockEC2KeyPairConn) CreateKeyPair(keyPairInput *ec2.CreateKeyPairInput) return output, nil } -func getKeyPairMockConn() ec2iface.EC2API { +func getKeyPairMockConn() clients.Ec2Client { return &mockEC2KeyPairConn{} } @@ -50,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 } @@ -79,7 +79,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 9ab3a49b0..4d6338b66 100644 --- a/builder/common/step_modify_ami_attributes.go +++ b/builder/common/step_modify_ami_attributes.go @@ -7,9 +7,9 @@ import ( "context" "fmt" - "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" + 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/packerbuilderdata" @@ -26,7 +26,7 @@ type StepModifyAMIAttributes struct { SnapshotUsers []string SnapshotGroups []string ProductCodes []string - IMDSSupport string + IMDSSupport ec2types.ImdsSupportValues Description string Ctx interpolate.Context @@ -34,8 +34,7 @@ type StepModifyAMIAttributes struct { } func (s *StepModifyAMIAttributes) 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 { @@ -63,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) @@ -77,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), } } @@ -102,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 @@ -120,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, @@ -195,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)), }, } } @@ -204,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) @@ -224,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 07304a57e..453134e6b 100644 --- a/builder/common/step_modify_ebs_instance.go +++ b/builder/common/step_modify_ebs_instance.go @@ -8,8 +8,9 @@ import ( "fmt" "strings" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "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" @@ -22,8 +23,8 @@ type StepModifyEBSBackedInstance struct { } func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(ec2iface.EC2API) - 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 @@ -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.go b/builder/common/step_network_info.go index 05f33d3d9..946d7a195 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 492ead81a..52b6cbd1c 100644 --- a/builder/common/step_network_info_test.go +++ b/builder/common/step_network_info_test.go @@ -9,42 +9,44 @@ import ( "strings" "testing" - "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/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" 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) - 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 +55,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 +73,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 +92,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 +113,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 +134,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 +150,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 +161,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 +170,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 +181,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"), @@ -195,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) } @@ -205,7 +207,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 +221,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 +251,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 +264,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 +292,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 +362,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 +463,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 +477,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 +507,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 +520,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 7b2a2e431..49a589938 100644 --- a/builder/common/step_pre_validate.go +++ b/builder/common/step_pre_validate.go @@ -9,10 +9,11 @@ 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/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/retry" @@ -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 ec2iface.EC2API) 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 ec2iface.EC2API) 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 be66dbc4c..1c8d7813c 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), }, @@ -51,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_source_instance.go b/builder/common/step_run_source_instance.go index f1fd83df7..f74dc8ed8 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,19 +342,19 @@ 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) } } - 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) @@ -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 9ac83b067..2b13d5d25 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,28 +28,28 @@ 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 @@ -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: ec2types.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, }) @@ -588,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) @@ -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 c729e4e94..2d4b88ab2 100644 --- a/builder/common/step_run_spot_instance_test.go +++ b/builder/common/step_run_spot_instance_test.go @@ -9,10 +9,10 @@ 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-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,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, @@ -69,7 +69,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 +91,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 +99,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 +111,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 +146,59 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { } type runSpotEC2ConnMock struct { - ec2iface.EC2API + //clients.Ec2Client + 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(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 +206,46 @@ 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, }, }, }, + State: &ec2types.InstanceState{ + Name: ec2types.InstanceStateNameRunning, + }, } 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 +258,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) @@ -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 { @@ -293,7 +300,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 +315,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 +327,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.") } @@ -329,10 +336,10 @@ 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 { + if ec2Mock.DescribeInstancesParams[0].InstanceIds[0] != *instanceId { t.Fatalf("instanceId should match from createFleet response") } @@ -340,13 +347,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") } } @@ -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_security_group.go b/builder/common/step_security_group.go index 2ace1db10..40434043f 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_set_generated_data.go b/builder/common/step_set_generated_data.go index 82e525ffc..a7e824a7e 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/common/step_source_ami_info.go b/builder/common/step_source_ami_info.go index b5600e5e2..8ef02de2d 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" @@ -20,17 +23,17 @@ 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 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/step_source_ami_info_test.go b/builder/common/step_source_ami_info_test.go index e16200323..9a53e2a3a 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/step_stop_ebs_instance.go b/builder/common/step_stop_ebs_instance.go index 776c9ac2d..91d5bd7c5 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 @@ -45,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 } @@ -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)*time.Second) if err != nil { err := fmt.Errorf("Error waiting for instance to stop: %s", err) state.Put("error", err) diff --git a/builder/common/tags.go b/builder/common/tags.go index c87f44699..aaa63b707 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 ...ec2types.ResourceType) []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: resource, Tags: t, } tagSpecs = append(tagSpecs, runTags) diff --git a/builder/common/test_helper_funcs.go b/builder/common/test_helper_funcs.go index 4976ea4b3..fbfc92250 100644 --- a/builder/common/test_helper_funcs.go +++ b/builder/common/test_helper_funcs.go @@ -4,25 +4,27 @@ 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), + AccessKey: "AKIA12SOME345EXAMPLE", + SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + Token: "accesstoken", + SkipCredsValidation: true, + PollingConfig: new(AWSPollingConfig).Prepare(), + } + accessConfig.awsConfig = &aws.Config{ + Region: "us-east-1", } - accessConfig.session = session.Must(session.NewSession(&aws.Config{ - Region: aws.String("us-west-1"), - })) - return &accessConfig } diff --git a/builder/ebs/builder.go b/builder/ebs/builder.go index 15ff88d24..6406ee7d1 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 fa76dc951..4e84cdf1b 100644 --- a/builder/ebs/step_create_ami.go +++ b/builder/ebs/step_create_ami.go @@ -35,9 +35,9 @@ 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) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) if s.AMISkipCreateImage { @@ -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/ebs/step_enable_fast_launch.go b/builder/ebs/step_enable_fast_launch.go index 628836fa1..646d00f40 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/ebssurrogate/builder.go b/builder/ebssurrogate/builder.go index aed268b84..96389290c 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 e618770fb..1981a92b3 100644 --- a/builder/ebssurrogate/step_create_ami.go +++ b/builder/ebssurrogate/step_create_ami.go @@ -38,9 +38,9 @@ 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) + instance := state.Get("instance").(*ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) blockDevices := s.combineDevices() @@ -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 6274977bc..7238afbb2 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 aae4ca149..f62f61496 100644 --- a/builder/ebssurrogate/step_snapshot_volumes.go +++ b/builder/ebssurrogate/step_snapshot_volumes.go @@ -37,10 +37,10 @@ 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) + instance := state.Get("instance").(*ec2types.Instance) var volumeId string for _, volume := range instance.BlockDeviceMappings { @@ -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 af335da22..5d4e5bec9 100644 --- a/builder/ebssurrogate/step_swap_volumes.go +++ b/builder/ebssurrogate/step_swap_volumes.go @@ -29,9 +29,9 @@ 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) + instance := state.Get("instance").(*ec2types.Instance) // Describe the instance input := &ec2.DescribeInstancesInput{ @@ -143,9 +143,9 @@ 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) + 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/builder.go b/builder/ebsvolume/builder.go index 5e195c15b..719cd9ded 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 87a6deba5..3d8d42e34 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 2903bcdf9..b179d4450 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 910809aa4..e1de7902c 100644 --- a/builder/ebsvolume/step_tag_ebs_volumes.go +++ b/builder/ebsvolume/step_tag_ebs_volumes.go @@ -24,8 +24,8 @@ type stepTagEBSVolumes struct { } func (s *stepTagEBSVolumes) 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) region := state.Get("region").(string) ui := state.Get("ui").(packersdk.Ui) config := state.Get("config").(*Config) diff --git a/builder/instance/builder.go b/builder/instance/builder.go index b84617916..7cdea3b49 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,24 +255,25 @@ 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) + state.Put("ctx", ctx) state.Put("config", &b.config) state.Put("access_config", &b.config.AccessConfig) 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 +292,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 +303,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 +401,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 +414,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 +460,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 +509,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/builder.hcl2spec.go b/builder/instance/builder.hcl2spec.go index 681678158..0fd3caa42 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/builder/instance/step_bundle_volume.go b/builder/instance/step_bundle_volume.go index 602fa2c3d..b1c9a2aeb 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/builder/instance/step_register_ami.go b/builder/instance/step_register_ami.go index 0aac3bb4c..bce7b92ef 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 231362bb4..b19731dcb 100644 --- a/builder/instance/step_upload_bundle.go +++ b/builder/instance/step_upload_bundle.go @@ -35,12 +35,17 @@ 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) + 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 == "" { - 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 22706c1fe..4a26fc2fc 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/ssh.go b/common/ssh.go index ff50cfac6..e910db82c 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 0170f9a74..7e0873beb 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 b134ccf3b..a17c1b7a4 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 f27ce395b..9fb3ab37c 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 834f1df54..b267bb690 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 cee9a7ea0..5049adfd7 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()) @@ -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{ @@ -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 4b5044344..d034b3ae4 100644 --- a/common/step_get_password.go +++ b/common/step_get_password.go @@ -104,8 +104,8 @@ 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) - instance := state.Get("instance").(ec2types.Instance) + ec2Client := state.Get("ec2").(clients.Ec2Client) + instance := state.Get("instance").(*ec2types.Instance) privateKey := s.Comm.SSHPrivateKey for { diff --git a/common/step_iam_instance_profile.go b/common/step_iam_instance_profile.go index bd3970ec2..3214d7130 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 ca9a55e40..5f90b56ad 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 264e0bcba..11b48803a 100644 --- a/common/step_modify_ebs_instance.go +++ b/common/step_modify_ebs_instance.go @@ -23,8 +23,8 @@ type StepModifyEBSBackedInstance struct { } func (s *StepModifyEBSBackedInstance) 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").(packersdk.Ui) // Skip when it is a spot instance diff --git a/common/step_network_info.go b/common/step_network_info.go index 41676e75b..9e96e2e6d 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 f8f150aed..6296964b0 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 839a8ac57..03e73059f 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 38dd2a230..3404e645b 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 3b9bd5d31..494723dc6 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" @@ -148,25 +146,25 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { } type runSpotEC2ConnMock struct { - //ec2iface.EC2API + //clients.Ec2Client 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 016415be5..38c71f38a 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 d2e6424ba..66806f2c7 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 27d6d2fcf..5dd7cce47 100644 --- a/common/step_stop_ebs_instance.go +++ b/common/step_stop_ebs_instance.go @@ -25,8 +25,8 @@ type StepStopEBSBackedInstance struct { } func (s *StepStopEBSBackedInstance) 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").(packersdk.Ui) // Skip when it is a spot instance diff --git a/docs-partials/builder/chroot/Config-not-required.mdx b/docs-partials/builder/chroot/Config-not-required.mdx index 1e2d9b55c..49b67dccc 100644 --- a/docs-partials/builder/chroot/Config-not-required.mdx +++ b/docs-partials/builder/chroot/Config-not-required.mdx @@ -71,7 +71,7 @@ - `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. diff --git a/docs-partials/builder/common/AMIConfig-not-required.mdx b/docs-partials/builder/common/AMIConfig-not-required.mdx index 1d1d9998b..b0c53961e 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 4333f877b..b16fb4bf8 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 2a11a512f..6878d7389 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 @@ -41,7 +41,7 @@ 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 b848477cd..3b296dcc0 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 d0eadce36..af9fc6057 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 fc0141688..6c6cfdc73 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 000000000..512446ce8 --- /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 a5a89eddf..d0b89415a 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 a8434e594..153e5f711 100644 --- a/go.mod +++ b/go.mod @@ -1,163 +1,180 @@ 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/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/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.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 + 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.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 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.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 ) -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 c824c3191..a20589fc6 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.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.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/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,84 @@ 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.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= +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,47 +137,44 @@ 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= 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 +183,104 @@ 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/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-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-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.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/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.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/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= @@ -299,17 +295,21 @@ 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= 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 +322,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= @@ -419,9 +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.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 +420,143 @@ 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.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-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-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= 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 +572,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=