Overview
Setting capacity_reservation_id (or capacity_reservation_group_arn) without also
setting capacity_reservation_preference causes the amazon-ebs builder to panic with a nil
pointer dereference at instance launch. Because run_config.go validation treats
capacity_reservation_id and capacity_reservation_preference as mutually exclusive, there
is no configuration in which capacity_reservation_id can be used at all — every valid config
that sets it crashes.
Reproduction
Minimal template (crash.pkr.hcl):
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1"
}
}
}
source "amazon-ebs" "t" {
region = "us-west-2"
instance_type = "g4dn.8xlarge"
source_ami = "ami-xxxxxxxxxxxxxxxxx" # any AMI
subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
communicator = "none"
skip_create_ami = true
ami_name = "crash-placeholder"
capacity_reservation_id = "cr-xxxxxxxxxxxxxxxxx" # a real, targeted ODCR in the subnet's AZ
}
build {
sources = ["source.amazon-ebs.t"]
}
packer init crash.pkr.hcl
packer build crash.pkr.hcl
Result — panic at the run-source-instance step:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=... addr=0x0 ...]
... github.com/hashicorp/packer-plugin-amazon/builder/common.(*StepRunSourceInstance).Run
.../builder/common/step_run_source_instance.go:263
If you instead add capacity_reservation_preference = "open" to try to avoid the crash, the
build fails validation before launch:
capacity_reservation_id, capacity_reservation_group_arn and capacity_reservation_preference
are mutually exclusive, only one should be set
So the two fields can never be combined, and capacity_reservation_id on its own always panics.
Root cause
In builder/common/step_run_source_instance.go, CapacityReservationSpecification is only
allocated inside the CapacityReservationPreference != "" branch:
if s.CapacityReservationPreference != "" {
runOpts.CapacityReservationSpecification = &ec2.CapacityReservationSpecification{
CapacityReservationPreference: aws.String(s.CapacityReservationPreference),
}
}
if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" {
// runOpts.CapacityReservationSpecification is still nil here when only the
// id/group_arn was provided -> nil pointer dereference on the next line.
runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2.CapacityReservationTarget{}
if s.CapacityReservationId != "" {
runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId = aws.String(s.CapacityReservationId)
}
if s.CapacityReservationGroupArn != "" {
runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn = aws.String(s.CapacityReservationGroupArn)
}
}
When only capacity_reservation_id/capacity_reservation_group_arn is set,
CapacityReservationSpecification is nil, and assigning .CapacityReservationTarget on it
dereferences the nil pointer. The one config that would allocate the spec
(CapacityReservationPreference) is rejected by run_config.go as mutually exclusive with the
target fields, so capacity_reservation_id is unusable in every valid configuration.
Suggested fix
Allocate the specification if it is nil before setting the target, e.g.:
if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" {
if runOpts.CapacityReservationSpecification == nil {
runOpts.CapacityReservationSpecification = &ec2.CapacityReservationSpecification{}
}
runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2.CapacityReservationTarget{}
...
}
(The same construction appears in the spot-instance run step and should be checked there too.)
Affected versions
- Reproduced on packer-plugin-amazon v1.3.9 (with Packer 1.13.1) and v1.8.1 (with Packer 1.15.4).
- The same code structure is present on
main, so it is not fixed in any released version.
Environment
- Packer: 1.13.1 and 1.15.4
- packer-plugin-amazon: 1.3.9 and 1.8.1
- Host OS: Linux (amd64)
Overview
Setting
capacity_reservation_id(orcapacity_reservation_group_arn) without alsosetting
capacity_reservation_preferencecauses theamazon-ebsbuilder to panic with a nilpointer dereference at instance launch. Because
run_config.govalidation treatscapacity_reservation_idandcapacity_reservation_preferenceas mutually exclusive, thereis no configuration in which
capacity_reservation_idcan be used at all — every valid configthat sets it crashes.
Reproduction
Minimal template (
crash.pkr.hcl):Result — panic at the run-source-instance step:
If you instead add
capacity_reservation_preference = "open"to try to avoid the crash, thebuild fails validation before launch:
So the two fields can never be combined, and
capacity_reservation_idon its own always panics.Root cause
In
builder/common/step_run_source_instance.go,CapacityReservationSpecificationis onlyallocated inside the
CapacityReservationPreference != ""branch:When only
capacity_reservation_id/capacity_reservation_group_arnis set,CapacityReservationSpecificationisnil, and assigning.CapacityReservationTargeton itdereferences the nil pointer. The one config that would allocate the spec
(
CapacityReservationPreference) is rejected byrun_config.goas mutually exclusive with thetarget fields, so
capacity_reservation_idis unusable in every valid configuration.Suggested fix
Allocate the specification if it is nil before setting the target, e.g.:
(The same construction appears in the spot-instance run step and should be checked there too.)
Affected versions
main, so it is not fixed in any released version.Environment