diff --git a/builder/common/step_modify_ebs_instance.go b/builder/common/step_modify_ebs_instance.go index 07304a57..15e42c28 100644 --- a/builder/common/step_modify_ebs_instance.go +++ b/builder/common/step_modify_ebs_instance.go @@ -19,18 +19,24 @@ type StepModifyEBSBackedInstance struct { Skip bool EnableAMIENASupport config.Trilean EnableAMISriovNetSupport bool + AMISkipCreateImage bool } func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(ec2iface.EC2API) - instance := state.Get("instance").(*ec2.Instance) - ui := state.Get("ui").(packersdk.Ui) - // Skip when it is a spot instance if s.Skip { return multistep.ActionContinue } + ui := state.Get("ui").(packersdk.Ui) + if s.AMISkipCreateImage { + ui.Say("skip_create_ami was set; skipping source instance attribute modification") + return multistep.ActionContinue + } + + ec2conn := state.Get("ec2").(ec2iface.EC2API) + instance := state.Get("instance").(*ec2.Instance) + // Set SriovNetSupport to "simple". See http://goo.gl/icuXh5 // As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge) if s.EnableAMISriovNetSupport { diff --git a/builder/common/step_modify_ebs_instance_test.go b/builder/common/step_modify_ebs_instance_test.go new file mode 100644 index 00000000..a017c6d1 --- /dev/null +++ b/builder/common/step_modify_ebs_instance_test.go @@ -0,0 +1,34 @@ +// Copyright IBM Corp. 2013, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package common + +import ( + "context" + "testing" + + "github.com/hashicorp/packer-plugin-sdk/multistep" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer-plugin-sdk/template/config" +) + +func TestStepModifyEBSBackedInstance_SkipCreateAMISkipsModification(t *testing.T) { + state := new(multistep.BasicStateBag) + state.Put("ui", packersdk.TestUi(t)) + + step := &StepModifyEBSBackedInstance{ + AMISkipCreateImage: true, + EnableAMISriovNetSupport: true, + EnableAMIENASupport: config.TriTrue, + } + + action := step.Run(context.Background(), state) + + if action != multistep.ActionContinue { + t.Fatalf("expected ActionContinue, got %v", action) + } + + if rawErr, ok := state.GetOk("error"); ok { + t.Fatalf("expected no error, got %v", rawErr) + } +} diff --git a/builder/common/step_stop_ebs_instance.go b/builder/common/step_stop_ebs_instance.go index 6225b648..e5362d3a 100644 --- a/builder/common/step_stop_ebs_instance.go +++ b/builder/common/step_stop_ebs_instance.go @@ -19,11 +19,10 @@ type StepStopEBSBackedInstance struct { PollingConfig *AWSPollingConfig Skip bool DisableStopInstance bool + AMISkipCreateImage bool } func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) - instance := state.Get("instance").(*ec2.Instance) ui := state.Get("ui").(packersdk.Ui) // Skip when it is a spot instance @@ -31,6 +30,14 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta return multistep.ActionContinue } + if s.AMISkipCreateImage { + ui.Say("skip_create_ami was set; skipping source instance stop") + return multistep.ActionContinue + } + + ec2conn := state.Get("ec2").(*ec2.EC2) + instance := state.Get("instance").(*ec2.Instance) + var err error if !s.DisableStopInstance { diff --git a/builder/common/step_stop_ebs_instance_test.go b/builder/common/step_stop_ebs_instance_test.go new file mode 100644 index 00000000..6841dfde --- /dev/null +++ b/builder/common/step_stop_ebs_instance_test.go @@ -0,0 +1,31 @@ +// Copyright IBM Corp. 2013, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package common + +import ( + "context" + "testing" + + "github.com/hashicorp/packer-plugin-sdk/multistep" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" +) + +func TestStepStopEBSBackedInstance_SkipCreateAMISkipsStop(t *testing.T) { + state := new(multistep.BasicStateBag) + state.Put("ui", packersdk.TestUi(t)) + + step := &StepStopEBSBackedInstance{ + AMISkipCreateImage: true, + } + + action := step.Run(context.Background(), state) + + if action != multistep.ActionContinue { + t.Fatalf("expected ActionContinue, got %v", action) + } + + if rawErr, ok := state.GetOk("error"); ok { + t.Fatalf("expected no error, got %v", rawErr) + } +} diff --git a/builder/ebs/builder.go b/builder/ebs/builder.go index 15ff88d2..165ec961 100644 --- a/builder/ebs/builder.go +++ b/builder/ebs/builder.go @@ -400,10 +400,12 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) PollingConfig: b.config.PollingConfig, Skip: b.config.IsSpotInstance(), DisableStopInstance: b.config.DisableStopInstance, + AMISkipCreateImage: b.config.AMISkipCreateImage, }, &awscommon.StepModifyEBSBackedInstance{ EnableAMISriovNetSupport: b.config.AMISriovNetSupport, EnableAMIENASupport: b.config.AMIENASupport, + AMISkipCreateImage: b.config.AMISkipCreateImage, }, &awscommon.StepDeregisterAMI{ AccessConfig: &b.config.AccessConfig, diff --git a/common/step_modify_ebs_instance.go b/common/step_modify_ebs_instance.go index 264e0bcb..fcac4ef6 100644 --- a/common/step_modify_ebs_instance.go +++ b/common/step_modify_ebs_instance.go @@ -20,18 +20,24 @@ type StepModifyEBSBackedInstance struct { Skip bool EnableAMIENASupport config.Trilean EnableAMISriovNetSupport bool + AMISkipCreateImage bool } func (s *StepModifyEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) - ui := state.Get("ui").(packersdk.Ui) - // Skip when it is a spot instance if s.Skip { return multistep.ActionContinue } + ui := state.Get("ui").(packersdk.Ui) + if s.AMISkipCreateImage { + ui.Say("skip_create_ami was set; skipping source instance attribute modification") + return multistep.ActionContinue + } + + ec2Client := state.Get("ec2v2").(clients.Ec2Client) + instance := state.Get("instance").(ec2types.Instance) + // Set SriovNetSupport to "simple". See http://goo.gl/icuXh5 // As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge) if s.EnableAMISriovNetSupport { diff --git a/common/step_modify_ebs_instance_test.go b/common/step_modify_ebs_instance_test.go new file mode 100644 index 00000000..a017c6d1 --- /dev/null +++ b/common/step_modify_ebs_instance_test.go @@ -0,0 +1,34 @@ +// Copyright IBM Corp. 2013, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package common + +import ( + "context" + "testing" + + "github.com/hashicorp/packer-plugin-sdk/multistep" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer-plugin-sdk/template/config" +) + +func TestStepModifyEBSBackedInstance_SkipCreateAMISkipsModification(t *testing.T) { + state := new(multistep.BasicStateBag) + state.Put("ui", packersdk.TestUi(t)) + + step := &StepModifyEBSBackedInstance{ + AMISkipCreateImage: true, + EnableAMISriovNetSupport: true, + EnableAMIENASupport: config.TriTrue, + } + + action := step.Run(context.Background(), state) + + if action != multistep.ActionContinue { + t.Fatalf("expected ActionContinue, got %v", action) + } + + if rawErr, ok := state.GetOk("error"); ok { + t.Fatalf("expected no error, got %v", rawErr) + } +} diff --git a/common/step_stop_ebs_instance.go b/common/step_stop_ebs_instance.go index 0b1ccd5a..80c915ff 100644 --- a/common/step_stop_ebs_instance.go +++ b/common/step_stop_ebs_instance.go @@ -22,11 +22,10 @@ type StepStopEBSBackedInstance struct { PollingConfig *AWSPollingConfig Skip bool DisableStopInstance bool + AMISkipCreateImage bool } func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2Client := state.Get("ec2v2").(clients.Ec2Client) - instance := state.Get("instance").(ec2types.Instance) ui := state.Get("ui").(packersdk.Ui) // Skip when it is a spot instance @@ -34,6 +33,14 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta return multistep.ActionContinue } + if s.AMISkipCreateImage { + ui.Say("skip_create_ami was set; skipping source instance stop") + return multistep.ActionContinue + } + + ec2Client := state.Get("ec2v2").(clients.Ec2Client) + instance := state.Get("instance").(ec2types.Instance) + var err error if !s.DisableStopInstance { diff --git a/common/step_stop_ebs_instance_test.go b/common/step_stop_ebs_instance_test.go new file mode 100644 index 00000000..6841dfde --- /dev/null +++ b/common/step_stop_ebs_instance_test.go @@ -0,0 +1,31 @@ +// Copyright IBM Corp. 2013, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package common + +import ( + "context" + "testing" + + "github.com/hashicorp/packer-plugin-sdk/multistep" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" +) + +func TestStepStopEBSBackedInstance_SkipCreateAMISkipsStop(t *testing.T) { + state := new(multistep.BasicStateBag) + state.Put("ui", packersdk.TestUi(t)) + + step := &StepStopEBSBackedInstance{ + AMISkipCreateImage: true, + } + + action := step.Run(context.Background(), state) + + if action != multistep.ActionContinue { + t.Fatalf("expected ActionContinue, got %v", action) + } + + if rawErr, ok := state.GetOk("error"); ok { + t.Fatalf("expected no error, got %v", rawErr) + } +}