From 72b056f1bbefc2bf52ad9225cf4cf7fb953b2aaa Mon Sep 17 00:00:00 2001 From: Harrison Ahearn Date: Wed, 21 Jan 2026 14:09:38 -0500 Subject: [PATCH] feat: add capacity_reservation_market_type configuration option Add support for specifying market type when using EC2 capacity reservations. This enables users to leverage interruptible capacity reservations and capacity blocks by setting the capacity_reservation_market_type field. Changes include: - Add CapacityReservationMarketType field to RunConfig - Add validation for market type values (interruptible-capacity-reservation, capacity-block) - Update StepRunSourceInstance to apply market type to instance launch options - Update all builder types (ebs, ebssurrogate, ebsvolume, instance) to pass through the new field - Regenerate HCL2 spec files for all builders - Update documentation with new configuration option Co-Authored-By: Claude --- builder/common/run_config.go | 19 +++ builder/common/step_run_source_instance.go | 11 ++ builder/ebs/builder.go | 1 + builder/ebs/builder.hcl2spec.go | 136 +++++++++--------- builder/ebssurrogate/builder.go | 1 + builder/ebssurrogate/builder.hcl2spec.go | 80 ++++++----- builder/ebsvolume/builder.go | 1 + builder/ebsvolume/builder.hcl2spec.go | 80 ++++++----- builder/instance/builder.go | 1 + builder/instance/builder.hcl2spec.go | 136 +++++++++--------- common/run_config.go | 19 +++ common/step_run_source_instance.go | 11 ++ .../builder/common/RunConfig-not-required.mdx | 5 + .../common/RunConfig-not-required.mdx | 5 + 14 files changed, 294 insertions(+), 212 deletions(-) diff --git a/builder/common/run_config.go b/builder/common/run_config.go index 16dc8cf8..3b099326 100644 --- a/builder/common/run_config.go +++ b/builder/common/run_config.go @@ -156,6 +156,11 @@ type RunConfig struct { // Provide the EC2 Capacity Reservation Group ARN that will be used by // Packer. CapacityReservationGroupArn string `mapstructure:"capacity_reservation_group_arn" required:"false"` + // The market type to use when launching instances with capacity reservations. + // Valid values are: `interruptible-capacity-reservation`, `capacity-block`, or empty string (for on-demand). + // Only set this when using interruptible capacity reservations or capacity blocks. + // Leave empty for standard on-demand capacity reservations. Defaults to empty string. + CapacityReservationMarketType string `mapstructure:"capacity_reservation_market_type" required:"false"` // Packer normally stops the build instance after all provisioners have // run. For Windows instances, it is sometimes desirable to [run @@ -924,6 +929,20 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf(`capacity_reservation_preference only accepts 'none' or 'open' values`)) } + // Validate capacity_reservation_market_type + if c.CapacityReservationMarketType != "" { + switch c.CapacityReservationMarketType { + case "interruptible-capacity-reservation", "capacity-block": + // Valid market types + default: + errs = append(errs, fmt.Errorf(`capacity_reservation_market_type only accepts 'interruptible-capacity-reservation' or 'capacity-block' values`)) + } + // Market type should only be used with a specific capacity reservation + if c.CapacityReservationId == "" && c.CapacityReservationGroupArn == "" { + errs = append(errs, fmt.Errorf(`capacity_reservation_market_type requires either capacity_reservation_id or capacity_reservation_group_arn to be set`)) + } + } + var tenancy string tenancies := []string{c.Placement.Tenancy, c.Tenancy} diff --git a/builder/common/step_run_source_instance.go b/builder/common/step_run_source_instance.go index f1fd83df..010d75c2 100644 --- a/builder/common/step_run_source_instance.go +++ b/builder/common/step_run_source_instance.go @@ -31,6 +31,7 @@ type StepRunSourceInstance struct { CapacityReservationPreference string CapacityReservationId string CapacityReservationGroupArn string + CapacityReservationMarketType string Comm *communicator.Config Ctx interpolate.Context Debug bool @@ -258,6 +259,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" { + if runOpts.CapacityReservationSpecification == nil { + runOpts.CapacityReservationSpecification = &ec2.CapacityReservationSpecification{} + } runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2.CapacityReservationTarget{} if s.CapacityReservationId != "" { @@ -267,6 +271,13 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa if s.CapacityReservationGroupArn != "" { runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn = aws.String(s.CapacityReservationGroupArn) } + + // Set market type if specified for interruptible capacity reservations or capacity blocks + if s.CapacityReservationMarketType != "" { + runOpts.InstanceMarketOptions = &ec2.InstanceMarketOptionsRequest{ + MarketType: aws.String(s.CapacityReservationMarketType), + } + } } if s.HostResourceGroupArn != "" { diff --git a/builder/ebs/builder.go b/builder/ebs/builder.go index 15ff88d2..223ed9b4 100644 --- a/builder/ebs/builder.go +++ b/builder/ebs/builder.go @@ -271,6 +271,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) CapacityReservationPreference: b.config.CapacityReservationPreference, CapacityReservationId: b.config.CapacityReservationId, CapacityReservationGroupArn: b.config.CapacityReservationGroupArn, + CapacityReservationMarketType: b.config.CapacityReservationMarketType, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, Debug: b.config.PackerDebug, diff --git a/builder/ebs/builder.hcl2spec.go b/builder/ebs/builder.hcl2spec.go index bcb315b0..4ec26c4c 100644 --- a/builder/ebs/builder.hcl2spec.go +++ b/builder/ebs/builder.hcl2spec.go @@ -70,6 +70,7 @@ type FlatConfig struct { CapacityReservationPreference *string `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"` + CapacityReservationMarketType *string `mapstructure:"capacity_reservation_market_type" required:"false" cty:"capacity_reservation_market_type" hcl:"capacity_reservation_market_type"` DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"` EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"` EnableNitroEnclave *bool `mapstructure:"enable_nitro_enclave" required:"false" cty:"enable_nitro_enclave" hcl:"enable_nitro_enclave"` @@ -182,73 +183,74 @@ func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } // The decoded values from this spec will then be applied to a FlatConfig. func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, - "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, - "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, - "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, - "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, - "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, - "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, - "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, - "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, - "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, - "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, - "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, - "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, - "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, - "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, - "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, - "ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false}, - "ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false}, - "ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false}, - "ami_users": &hcldec.AttrSpec{Name: "ami_users", Type: cty.List(cty.String), Required: false}, - "ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false}, - "ami_org_arns": &hcldec.AttrSpec{Name: "ami_org_arns", Type: cty.List(cty.String), Required: false}, - "ami_ou_arns": &hcldec.AttrSpec{Name: "ami_ou_arns", Type: cty.List(cty.String), Required: false}, - "ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false}, - "ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false}, - "skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false}, - "snapshot_copy_duration_minutes": &hcldec.AttrSpec{Name: "snapshot_copy_duration_minutes", Type: cty.Number, Required: false}, - "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false}, - "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false}, - "sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false}, - "force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false}, - "force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false}, - "encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false}, - "kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false}, - "region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false}, - "skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false}, - "imds_support": &hcldec.AttrSpec{Name: "imds_support", Type: cty.String, Required: false}, - "deprecate_at": &hcldec.AttrSpec{Name: "deprecate_at", Type: cty.String, Required: false}, - "snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false}, - "snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false}, - "snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false}, - "deregistration_protection": &hcldec.BlockSpec{TypeName: "deregistration_protection", Nested: hcldec.ObjectSpec((*common.FlatDeregistrationProtectionOptions)(nil).HCL2Spec())}, - "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, - "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, - "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, - "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, - "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, - "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, - "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, - "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, - "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, - "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, - "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, - "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, - "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, - "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, + "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, + "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, + "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, + "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, + "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, + "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, + "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, + "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, + "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, + "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, + "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, + "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, + "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, + "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, + "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, + "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, + "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, + "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, + "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, + "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, + "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, + "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, + "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, + "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, + "ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false}, + "ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false}, + "ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false}, + "ami_users": &hcldec.AttrSpec{Name: "ami_users", Type: cty.List(cty.String), Required: false}, + "ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false}, + "ami_org_arns": &hcldec.AttrSpec{Name: "ami_org_arns", Type: cty.List(cty.String), Required: false}, + "ami_ou_arns": &hcldec.AttrSpec{Name: "ami_ou_arns", Type: cty.List(cty.String), Required: false}, + "ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false}, + "ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false}, + "skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false}, + "snapshot_copy_duration_minutes": &hcldec.AttrSpec{Name: "snapshot_copy_duration_minutes", Type: cty.Number, Required: false}, + "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false}, + "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false}, + "sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false}, + "force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false}, + "force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false}, + "encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false}, + "kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false}, + "region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false}, + "skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false}, + "imds_support": &hcldec.AttrSpec{Name: "imds_support", Type: cty.String, Required: false}, + "deprecate_at": &hcldec.AttrSpec{Name: "deprecate_at", Type: cty.String, Required: false}, + "snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false}, + "snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false}, + "snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false}, + "deregistration_protection": &hcldec.BlockSpec{TypeName: "deregistration_protection", Nested: hcldec.ObjectSpec((*common.FlatDeregistrationProtectionOptions)(nil).HCL2Spec())}, + "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, + "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, + "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, + "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, + "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, + "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, + "capacity_reservation_market_type": &hcldec.AttrSpec{Name: "capacity_reservation_market_type", Type: cty.String, Required: false}, + "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, + "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, + "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, + "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, + "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, + "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, + "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, + "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, "temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())}, "shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false}, "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, diff --git a/builder/ebssurrogate/builder.go b/builder/ebssurrogate/builder.go index aed268b8..a5bcac0c 100644 --- a/builder/ebssurrogate/builder.go +++ b/builder/ebssurrogate/builder.go @@ -308,6 +308,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) CapacityReservationPreference: b.config.CapacityReservationPreference, CapacityReservationId: b.config.CapacityReservationId, CapacityReservationGroupArn: b.config.CapacityReservationGroupArn, + CapacityReservationMarketType: b.config.CapacityReservationMarketType, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, Debug: b.config.PackerDebug, diff --git a/builder/ebssurrogate/builder.hcl2spec.go b/builder/ebssurrogate/builder.hcl2spec.go index 86eaafa1..0bf2713a 100644 --- a/builder/ebssurrogate/builder.hcl2spec.go +++ b/builder/ebssurrogate/builder.hcl2spec.go @@ -87,6 +87,7 @@ type FlatConfig struct { CapacityReservationPreference *string `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"` + CapacityReservationMarketType *string `mapstructure:"capacity_reservation_market_type" required:"false" cty:"capacity_reservation_market_type" hcl:"capacity_reservation_market_type"` DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"` EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"` EnableNitroEnclave *bool `mapstructure:"enable_nitro_enclave" required:"false" cty:"enable_nitro_enclave" hcl:"enable_nitro_enclave"` @@ -231,45 +232,46 @@ func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } // The decoded values from this spec will then be applied to a FlatConfig. func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, - "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, - "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, - "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, - "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, - "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, - "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, - "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, - "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, - "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, - "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, - "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, - "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, - "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, - "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, - "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, - "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, - "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, - "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, - "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, - "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, - "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, - "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, - "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, - "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, - "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, - "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, - "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, - "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, - "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, + "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, + "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, + "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, + "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, + "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, + "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, + "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, + "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, + "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, + "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, + "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, + "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, + "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, + "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, + "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, + "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, + "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, + "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, + "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, + "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, + "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, + "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, + "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, + "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, + "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, + "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, + "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, + "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, + "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, + "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, + "capacity_reservation_market_type": &hcldec.AttrSpec{Name: "capacity_reservation_market_type", Type: cty.String, Required: false}, + "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, + "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, + "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, + "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, + "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, + "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, + "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, + "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, "temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())}, "shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false}, "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, diff --git a/builder/ebsvolume/builder.go b/builder/ebsvolume/builder.go index 5e195c15..e08b153f 100644 --- a/builder/ebsvolume/builder.go +++ b/builder/ebsvolume/builder.go @@ -254,6 +254,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) CapacityReservationPreference: b.config.CapacityReservationPreference, CapacityReservationId: b.config.CapacityReservationId, CapacityReservationGroupArn: b.config.CapacityReservationGroupArn, + CapacityReservationMarketType: b.config.CapacityReservationMarketType, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, Debug: b.config.PackerDebug, diff --git a/builder/ebsvolume/builder.hcl2spec.go b/builder/ebsvolume/builder.hcl2spec.go index f208ddb4..b752cd31 100644 --- a/builder/ebsvolume/builder.hcl2spec.go +++ b/builder/ebsvolume/builder.hcl2spec.go @@ -101,6 +101,7 @@ type FlatConfig struct { CapacityReservationPreference *string `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"` + CapacityReservationMarketType *string `mapstructure:"capacity_reservation_market_type" required:"false" cty:"capacity_reservation_market_type" hcl:"capacity_reservation_market_type"` DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"` EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"` EnableNitroEnclave *bool `mapstructure:"enable_nitro_enclave" required:"false" cty:"enable_nitro_enclave" hcl:"enable_nitro_enclave"` @@ -210,45 +211,46 @@ func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } // The decoded values from this spec will then be applied to a FlatConfig. func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, - "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, - "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, - "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, - "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, - "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, - "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, - "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, - "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, - "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, - "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, - "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, - "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, - "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, - "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, - "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, - "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, - "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, - "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, - "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, - "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, - "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, - "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, - "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, - "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, - "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, - "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, - "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, - "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, - "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, + "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, + "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, + "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, + "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, + "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, + "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, + "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, + "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, + "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, + "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, + "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, + "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, + "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, + "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, + "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, + "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, + "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, + "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, + "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, + "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, + "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, + "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, + "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, + "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, + "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, + "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, + "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, + "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, + "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, + "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, + "capacity_reservation_market_type": &hcldec.AttrSpec{Name: "capacity_reservation_market_type", Type: cty.String, Required: false}, + "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, + "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, + "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, + "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, + "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, + "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, + "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, + "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, "temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())}, "shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false}, "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, diff --git a/builder/instance/builder.go b/builder/instance/builder.go index b8461791..09d5e077 100644 --- a/builder/instance/builder.go +++ b/builder/instance/builder.go @@ -318,6 +318,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) CapacityReservationPreference: b.config.CapacityReservationPreference, CapacityReservationId: b.config.CapacityReservationId, CapacityReservationGroupArn: b.config.CapacityReservationGroupArn, + CapacityReservationMarketType: b.config.CapacityReservationMarketType, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, Debug: b.config.PackerDebug, diff --git a/builder/instance/builder.hcl2spec.go b/builder/instance/builder.hcl2spec.go index 68167815..54d308e5 100644 --- a/builder/instance/builder.hcl2spec.go +++ b/builder/instance/builder.hcl2spec.go @@ -70,6 +70,7 @@ type FlatConfig struct { CapacityReservationPreference *string `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"` + CapacityReservationMarketType *string `mapstructure:"capacity_reservation_market_type" required:"false" cty:"capacity_reservation_market_type" hcl:"capacity_reservation_market_type"` DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"` EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"` EnableNitroEnclave *bool `mapstructure:"enable_nitro_enclave" required:"false" cty:"enable_nitro_enclave" hcl:"enable_nitro_enclave"` @@ -186,73 +187,74 @@ func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } // The decoded values from this spec will then be applied to a FlatConfig. func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, - "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, - "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, - "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, - "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, - "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, - "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, - "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, - "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, - "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, - "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, - "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, - "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, - "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, - "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, - "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, - "ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false}, - "ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false}, - "ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false}, - "ami_users": &hcldec.AttrSpec{Name: "ami_users", Type: cty.List(cty.String), Required: false}, - "ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false}, - "ami_org_arns": &hcldec.AttrSpec{Name: "ami_org_arns", Type: cty.List(cty.String), Required: false}, - "ami_ou_arns": &hcldec.AttrSpec{Name: "ami_ou_arns", Type: cty.List(cty.String), Required: false}, - "ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false}, - "ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false}, - "skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false}, - "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false}, - "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false}, - "sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false}, - "force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false}, - "force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false}, - "encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false}, - "kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false}, - "region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false}, - "skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false}, - "snapshot_copy_duration_minutes": &hcldec.AttrSpec{Name: "snapshot_copy_duration_minutes", Type: cty.Number, Required: false}, - "imds_support": &hcldec.AttrSpec{Name: "imds_support", Type: cty.String, Required: false}, - "deprecate_at": &hcldec.AttrSpec{Name: "deprecate_at", Type: cty.String, Required: false}, - "snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false}, - "snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false}, - "snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false}, - "deregistration_protection": &hcldec.BlockSpec{TypeName: "deregistration_protection", Nested: hcldec.ObjectSpec((*common.FlatDeregistrationProtectionOptions)(nil).HCL2Spec())}, - "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, - "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, - "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, - "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, - "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, - "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, - "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, - "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, - "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, - "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, - "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, - "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, - "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, - "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, - "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, + "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, + "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, + "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, + "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, + "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, + "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, + "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, + "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, + "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, + "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())}, + "custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false}, + "shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false}, + "decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false}, + "insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false}, + "max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false}, + "mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false}, + "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, + "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, + "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, + "skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false}, + "skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", Type: cty.Bool, Required: false}, + "token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false}, + "vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())}, + "aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())}, + "ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false}, + "ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false}, + "ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false}, + "ami_users": &hcldec.AttrSpec{Name: "ami_users", Type: cty.List(cty.String), Required: false}, + "ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false}, + "ami_org_arns": &hcldec.AttrSpec{Name: "ami_org_arns", Type: cty.List(cty.String), Required: false}, + "ami_ou_arns": &hcldec.AttrSpec{Name: "ami_ou_arns", Type: cty.List(cty.String), Required: false}, + "ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false}, + "ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false}, + "skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false}, + "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false}, + "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false}, + "sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false}, + "force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false}, + "force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false}, + "encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false}, + "kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false}, + "region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false}, + "skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false}, + "snapshot_copy_duration_minutes": &hcldec.AttrSpec{Name: "snapshot_copy_duration_minutes", Type: cty.Number, Required: false}, + "imds_support": &hcldec.AttrSpec{Name: "imds_support", Type: cty.String, Required: false}, + "deprecate_at": &hcldec.AttrSpec{Name: "deprecate_at", Type: cty.String, Required: false}, + "snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false}, + "snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false}, + "snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false}, + "deregistration_protection": &hcldec.BlockSpec{TypeName: "deregistration_protection", Nested: hcldec.ObjectSpec((*common.FlatDeregistrationProtectionOptions)(nil).HCL2Spec())}, + "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, + "availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false}, + "block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false}, + "capacity_reservation_preference": &hcldec.AttrSpec{Name: "capacity_reservation_preference", Type: cty.String, Required: false}, + "capacity_reservation_id": &hcldec.AttrSpec{Name: "capacity_reservation_id", Type: cty.String, Required: false}, + "capacity_reservation_group_arn": &hcldec.AttrSpec{Name: "capacity_reservation_group_arn", Type: cty.String, Required: false}, + "capacity_reservation_market_type": &hcldec.AttrSpec{Name: "capacity_reservation_market_type", Type: cty.String, Required: false}, + "disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false}, + "ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false}, + "enable_nitro_enclave": &hcldec.AttrSpec{Name: "enable_nitro_enclave", Type: cty.Bool, Required: false}, + "enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false}, + "enable_unlimited_credits": &hcldec.AttrSpec{Name: "enable_unlimited_credits", Type: cty.Bool, Required: false}, + "iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false}, + "fleet_tags": &hcldec.AttrSpec{Name: "fleet_tags", Type: cty.Map(cty.String), Required: false}, + "fleet_tag": &hcldec.BlockListSpec{TypeName: "fleet_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())}, + "skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false}, "temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())}, "shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false}, "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, diff --git a/common/run_config.go b/common/run_config.go index 6cd68ba8..f8500dcc 100644 --- a/common/run_config.go +++ b/common/run_config.go @@ -153,6 +153,11 @@ type RunConfig struct { // Provide the EC2 Capacity Reservation Group ARN that will be used by // Packer. CapacityReservationGroupArn string `mapstructure:"capacity_reservation_group_arn" required:"false"` + // The market type to use when launching instances with capacity reservations. + // Valid values are: `interruptible-capacity-reservation`, `capacity-block`, or empty string (for on-demand). + // Only set this when using interruptible capacity reservations or capacity blocks. + // Leave empty for standard on-demand capacity reservations. Defaults to empty string. + CapacityReservationMarketType string `mapstructure:"capacity_reservation_market_type" required:"false"` // Packer normally stops the build instance after all provisioners have // run. For Windows instances, it is sometimes desirable to [run @@ -913,6 +918,20 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf(`capacity_reservation_preference only accepts 'none' or 'open' values`)) } + // Validate capacity_reservation_market_type + if c.CapacityReservationMarketType != "" { + switch c.CapacityReservationMarketType { + case "interruptible-capacity-reservation", "capacity-block": + // Valid market types + default: + errs = append(errs, fmt.Errorf(`capacity_reservation_market_type only accepts 'interruptible-capacity-reservation' or 'capacity-block' values`)) + } + // Market type should only be used with a specific capacity reservation + if c.CapacityReservationId == "" && c.CapacityReservationGroupArn == "" { + errs = append(errs, fmt.Errorf(`capacity_reservation_market_type requires either capacity_reservation_id or capacity_reservation_group_arn to be set`)) + } + } + var tenancy string tenancies := []string{c.Placement.Tenancy, c.Tenancy} diff --git a/common/step_run_source_instance.go b/common/step_run_source_instance.go index 839a8ac5..44b6e065 100644 --- a/common/step_run_source_instance.go +++ b/common/step_run_source_instance.go @@ -32,6 +32,7 @@ type StepRunSourceInstance struct { CapacityReservationPreference string CapacityReservationId string CapacityReservationGroupArn string + CapacityReservationMarketType string Comm *communicator.Config Ctx interpolate.Context Debug bool @@ -260,6 +261,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" { + if runOpts.CapacityReservationSpecification == nil { + runOpts.CapacityReservationSpecification = &ec2types.CapacityReservationSpecification{} + } runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2types.CapacityReservationTarget{} if s.CapacityReservationId != "" { @@ -269,6 +273,13 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa if s.CapacityReservationGroupArn != "" { runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn = aws.String(s.CapacityReservationGroupArn) } + + // Set market type if specified for interruptible capacity reservations or capacity blocks + if s.CapacityReservationMarketType != "" { + runOpts.InstanceMarketOptions = &ec2types.InstanceMarketOptionsRequest{ + MarketType: ec2types.MarketType(s.CapacityReservationMarketType), + } + } } if s.HostResourceGroupArn != "" { diff --git a/docs-partials/builder/common/RunConfig-not-required.mdx b/docs-partials/builder/common/RunConfig-not-required.mdx index d0eadce3..afcec6ce 100644 --- a/docs-partials/builder/common/RunConfig-not-required.mdx +++ b/docs-partials/builder/common/RunConfig-not-required.mdx @@ -39,6 +39,11 @@ - `capacity_reservation_group_arn` (string) - Provide the EC2 Capacity Reservation Group ARN that will be used by Packer. +- `capacity_reservation_market_type` (string) - The market type to use when launching instances with capacity reservations. + Valid values are: `interruptible-capacity-reservation`, `capacity-block`, or empty string (for on-demand). + Only set this when using interruptible capacity reservations or capacity blocks. + Leave empty for standard on-demand capacity reservations. Defaults to empty string. + - `disable_stop_instance` (bool) - Packer normally stops the build instance after all provisioners have run. For Windows instances, it is sometimes desirable to [run Sysprep](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/Creating_EBSbacked_WinAMI.html) diff --git a/docs-partials/common/RunConfig-not-required.mdx b/docs-partials/common/RunConfig-not-required.mdx index 8cfb0ca8..c80b5c6c 100644 --- a/docs-partials/common/RunConfig-not-required.mdx +++ b/docs-partials/common/RunConfig-not-required.mdx @@ -40,6 +40,11 @@ - `capacity_reservation_group_arn` (string) - Provide the EC2 Capacity Reservation Group ARN that will be used by Packer. +- `capacity_reservation_market_type` (string) - The market type to use when launching instances with capacity reservations. + Valid values are: `interruptible-capacity-reservation`, `capacity-block`, or empty string (for on-demand). + Only set this when using interruptible capacity reservations or capacity blocks. + Leave empty for standard on-demand capacity reservations. Defaults to empty string. + - `disable_stop_instance` (bool) - Packer normally stops the build instance after all provisioners have run. For Windows instances, it is sometimes desirable to [run Sysprep](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/Creating_EBSbacked_WinAMI.html)