From d561b404d678ac48a8a156aea5464ec3c128bd87 Mon Sep 17 00:00:00 2001 From: Aleksandr Serbin Date: Sun, 1 Nov 2020 15:43:49 +0100 Subject: [PATCH 1/3] amazon-ebs: add tags to launch template --- builder/amazon/chroot/builder.go | 1 + .../common/interpolate_build_info_test.go | 1 + .../amazon/common/step_run_spot_instance.go | 16 +- .../common/step_run_spot_instance_test.go | 190 ++++++++++++++++++ builder/amazon/ebs/builder.go | 1 + builder/amazon/ebssurrogate/builder.go | 1 + builder/amazon/ebsvolume/builder.go | 1 + builder/amazon/instance/builder.go | 1 + 8 files changed, 208 insertions(+), 4 deletions(-) diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index 9fb431583..1af8156c6 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -368,6 +368,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) + state.Put("region", *ec2conn.Config.Region) state.Put("wrappedCommand", common.CommandWrapper(wrappedCommand)) generatedData := &builder.GeneratedData{State: state} diff --git a/builder/amazon/common/interpolate_build_info_test.go b/builder/amazon/common/interpolate_build_info_test.go index a29f82dac..7a9da1866 100644 --- a/builder/amazon/common/interpolate_build_info_test.go +++ b/builder/amazon/common/interpolate_build_info_test.go @@ -17,6 +17,7 @@ func testImage() *ec2.Image { 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{ { Key: aws.String("key-1"), diff --git a/builder/amazon/common/step_run_spot_instance.go b/builder/amazon/common/step_run_spot_instance.go index 75ec401e9..1d80b924a 100644 --- a/builder/amazon/common/step_run_spot_instance.go +++ b/builder/amazon/common/step_run_spot_instance.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/hashicorp/packer/builder/amazon/common/awserrors" "github.com/hashicorp/packer/common/random" "github.com/hashicorp/packer/common/retry" @@ -158,8 +159,9 @@ func (s *StepRunSpotInstance) LoadUserData() (string, error) { } func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(ec2iface.EC2API) ui := state.Get("ui").(packer.Ui) + region := state.Get("region").(string) ui.Say("Launching a spot AWS instance...") @@ -197,7 +199,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } // Convert tags from the tag map provided by the user into *ec2.Tag s - ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, region, state) if err != nil { err := fmt.Errorf("Error generating tags for source instance: %s", err) state.Put("error", err) @@ -242,6 +244,12 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) LaunchTemplateData: templateData, LaunchTemplateName: aws.String(launchTemplateName), VersionDescription: aws.String("template generated by packer for launching spot instances"), + TagSpecifications: []*ec2.TagSpecification{ + { + ResourceType: aws.String("launch-template"), + Tags: ec2Tags, + }, + }, } // Tell EC2 to create the template @@ -361,7 +369,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) instance := describeOutput.Reservations[0].Instances[0] // Tag the spot instance request (not the eventual spot instance) - spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, region, state) if err != nil { err := fmt.Errorf("Error generating tags for spot request: %s", err) state.Put("error", err) @@ -428,7 +436,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) 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, region, state) if err != nil { err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err) state.Put("error", err) diff --git a/builder/amazon/common/step_run_spot_instance_test.go b/builder/amazon/common/step_run_spot_instance_test.go index 89fa53f01..4a57d0cbd 100644 --- a/builder/amazon/common/step_run_spot_instance_test.go +++ b/builder/amazon/common/step_run_spot_instance_test.go @@ -2,11 +2,13 @@ package common import ( "bytes" + "context" "fmt" "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/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -134,3 +136,191 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) { // t.Fatalf("Should have created 26 mappings to keep ephemeral drives from appearing.") // } } + +type runSpotEC2ConnMock struct { + ec2iface.EC2API + + CreateLaunchTemplateParams []*ec2.CreateLaunchTemplateInput + CreateLaunchTemplateFn func(*ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) + + CreateFleetParams []*ec2.CreateFleetInput + CreateFleetFn func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) + + CreateTagsParams []*ec2.CreateTagsInput + CreateTagsFn func(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) + + DescribeInstancesParams []*ec2.DescribeInstancesInput + DescribeInstancesFn func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) +} + +func (m *runSpotEC2ConnMock) CreateLaunchTemplate(req *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { + m.CreateLaunchTemplateParams = append(m.CreateLaunchTemplateParams, req) + resp, err := m.CreateLaunchTemplateFn(req) + return resp, err +} + +func (m *runSpotEC2ConnMock) CreateFleet(req *ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) { + m.CreateFleetParams = append(m.CreateFleetParams, req) + if m.CreateFleetFn != nil { + resp, err := m.CreateFleetFn(req) + return resp, err + } else { + return nil, nil + } +} + +func (m *runSpotEC2ConnMock) DescribeInstances(req *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { + m.DescribeInstancesParams = append(m.DescribeInstancesParams, req) + if m.DescribeInstancesFn != nil { + resp, err := m.DescribeInstancesFn(req) + return resp, err + } else { + return nil, nil + } +} + +func (m *runSpotEC2ConnMock) CreateTags(req *ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) { + m.CreateTagsParams = append(m.CreateTagsParams, req) + if m.CreateTagsFn != nil { + resp, err := m.CreateTagsFn(req) + return resp, err + } else { + return nil, nil + } +} + +func TestRun(t *testing.T) { + instanceId := aws.String("test-instance-id") + spotRequestId := aws.String("spot-id") + volumeId := aws.String("volume-id") + instance := &ec2.Instance{ + InstanceId: instanceId, + SpotInstanceRequestId: spotRequestId, + BlockDeviceMappings: []*ec2.InstanceBlockDeviceMapping{ + { + Ebs: &ec2.EbsInstanceBlockDevice{ + VolumeId: volumeId, + }, + }, + }, + } + ec2Mock := &runSpotEC2ConnMock{ + CreateLaunchTemplateFn: func(in *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { + return &ec2.CreateLaunchTemplateOutput{ + LaunchTemplate: nil, + Warning: nil, + }, nil + }, + CreateFleetFn: func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) { + return &ec2.CreateFleetOutput{ + Errors: nil, + FleetId: nil, + Instances: []*ec2.CreateFleetInstance{ + { + InstanceIds: []*string{instanceId}, + }, + }, + }, nil + }, + DescribeInstancesFn: func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { + return &ec2.DescribeInstancesOutput{ + NextToken: nil, + Reservations: []*ec2.Reservation{ + { + Instances: []*ec2.Instance{instance}, + }, + }, + }, nil + }, + } + + uiMock := packer.TestUi(t) + + state := tStateSpot() + state.Put("ec2", ec2Mock) + state.Put("ui", uiMock) + state.Put("source_image", testImage()) + state.Put("region", "test-region") + + stepRunSpotInstance := getBasicStep() + stepRunSpotInstance.Tags["Name"] = "Packer Builder" + stepRunSpotInstance.Tags["test-tag"] = "test-value" + stepRunSpotInstance.SpotTags = map[string]string{ + "spot-tag": "spot-tag-value", + } + stepRunSpotInstance.VolumeTags = map[string]string{ + "volume-tag": "volume-tag-value", + } + + ctx := context.TODO() + action := stepRunSpotInstance.Run(ctx, state) + + if err := state.Get("error"); err != nil { + t.Fatalf("should not error, but: %v", err) + } + + if action != multistep.ActionContinue { + t.Fatalf("shoul continue, but: %v", action) + } + + if len(ec2Mock.CreateLaunchTemplateParams) != 1 { + t.Fatalf("createLaunchTemplate should be invoked once, but invoked %v", len(ec2Mock.CreateLaunchTemplateParams)) + } + launchTemplateName := ec2Mock.CreateLaunchTemplateParams[0].LaunchTemplateName + + 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" { + t.Fatalf("resource type 'launch-template' expected") + } + if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags) != 2 { + t.Fatalf("2 tags expected") + } + + nameTag := ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags[0] + if *nameTag.Key != "Name" || *nameTag.Value != "Packer Builder" { + t.Fatalf("expected name tag") + } + testTag := ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags[1] + if *testTag.Key != "test-tag" || *testTag.Value != "test-value" { + t.Fatalf("expected test tag") + } + + 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" { + t.Fatalf("capacity type should be spot") + } + if *ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.TotalTargetCapacity != 1 { + t.Fatalf("target capacity should be 1") + } + if len(ec2Mock.CreateFleetParams[0].LaunchTemplateConfigs) != 1 { + t.Fatalf("exactly one launch config template expected") + } + if *ec2Mock.CreateFleetParams[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification.LaunchTemplateName != *launchTemplateName { + t.Fatalf("launchTemplateName should match in createLaunchTemplate and createFleet requests") + } + + if len(ec2Mock.DescribeInstancesParams) != 1 { + t.Fatalf("describeInstancesParams should be invoked once, but invoked %v", len(ec2Mock.DescribeInstancesParams)) + } + if *ec2Mock.DescribeInstancesParams[0].InstanceIds[0] != *instanceId { + t.Fatalf("instanceId should match from createFleet response") + } + + uiMock.Say(fmt.Sprintf("%v", ec2Mock.CreateTagsParams)) + 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 { + t.Fatalf("should create tags for spot request") + } + 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 { + t.Fatalf("should create tags for volume") + } +} diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 4d4934c43..8c4f00fe2 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -164,6 +164,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) + state.Put("region", *ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index c70026b3e..6600850f6 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -187,6 +187,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) + state.Put("region", *ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index d3fb1a03f..f9cb3b819 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -168,6 +168,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("iam", iam) state.Put("hook", hook) state.Put("ui", ui) + state.Put("region", *ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 7c050b88e..214f16283 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -250,6 +250,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) + state.Put("region", ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step From 8dab31b5480d7275a0ab2159b100dcf395d1ea27 Mon Sep 17 00:00:00 2001 From: Aleksandr Serbin Date: Tue, 3 Nov 2020 22:15:44 +0100 Subject: [PATCH 2/3] amazon: use spot tags for launch template tags - use `spot_tags` instead of `run_tags` for launch template - move region to `StepRunSpotInstance` from state --- .../amazon/common/step_run_spot_instance.go | 30 +++++---- .../common/step_run_spot_instance_test.go | 64 +++++++++++++++---- builder/amazon/ebs/builder.go | 2 +- builder/amazon/ebssurrogate/builder.go | 2 +- builder/amazon/ebsvolume/builder.go | 2 +- builder/amazon/instance/builder.go | 2 +- 6 files changed, 70 insertions(+), 32 deletions(-) diff --git a/builder/amazon/common/step_run_spot_instance.go b/builder/amazon/common/step_run_spot_instance.go index 1d80b924a..dc196817a 100644 --- a/builder/amazon/common/step_run_spot_instance.go +++ b/builder/amazon/common/step_run_spot_instance.go @@ -36,6 +36,7 @@ type StepRunSpotInstance struct { ExpectedRootDevice string InstanceInitiatedShutdownBehavior string InstanceType string + Region string SourceAMI string SpotPrice string SpotTags map[string]string @@ -161,7 +162,6 @@ func (s *StepRunSpotInstance) LoadUserData() (string, error) { func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ec2conn := state.Get("ec2").(ec2iface.EC2API) ui := state.Get("ui").(packer.Ui) - region := state.Get("region").(string) ui.Say("Launching a spot AWS instance...") @@ -199,7 +199,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } // Convert tags from the tag map provided by the user into *ec2.Tag s - ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, region, state) + ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, s.Region, state) if err != nil { err := fmt.Errorf("Error generating tags for source instance: %s", err) state.Put("error", err) @@ -223,6 +223,14 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } marketOptions.SetMarketType(ec2.MarketTypeSpot) + spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, s.Region, state) + if err != nil { + err := fmt.Errorf("Error generating tags for spot request: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + // Create a launch template for the instance ui.Message("Loading User Data File...") @@ -244,12 +252,14 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) LaunchTemplateData: templateData, LaunchTemplateName: aws.String(launchTemplateName), VersionDescription: aws.String("template generated by packer for launching spot instances"), - TagSpecifications: []*ec2.TagSpecification{ + } + if len(spotTags) > 0 { + launchTemplate.TagSpecifications = []*ec2.TagSpecification{ { ResourceType: aws.String("launch-template"), - Tags: ec2Tags, + Tags: spotTags, }, - }, + } } // Tell EC2 to create the template @@ -369,14 +379,6 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) instance := describeOutput.Reservations[0].Instances[0] // Tag the spot instance request (not the eventual spot instance) - spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, region, state) - if err != nil { - err := fmt.Errorf("Error generating tags for spot request: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - if len(spotTags) > 0 && len(s.SpotTags) > 0 { spotTags.Report(ui) // Use the instance ID to find out the SIR, so that we can tag the spot @@ -436,7 +438,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) if len(volumeIds) > 0 && len(s.VolumeTags) > 0 { ui.Say("Adding tags to source EBS Volumes") - volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, region, state) + volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, s.Region, state) if err != nil { err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err) state.Put("error", err) diff --git a/builder/amazon/common/step_run_spot_instance_test.go b/builder/amazon/common/step_run_spot_instance_test.go index 4a57d0cbd..d00bf74dd 100644 --- a/builder/amazon/common/step_run_spot_instance_test.go +++ b/builder/amazon/common/step_run_spot_instance_test.go @@ -45,6 +45,7 @@ func getBasicStep() *StepRunSpotInstance { ExpectedRootDevice: "ebs", InstanceInitiatedShutdownBehavior: "stop", InstanceType: "t2.micro", + Region: "us-east-1", SourceAMI: "", SpotPrice: "auto", SpotTags: nil, @@ -189,10 +190,7 @@ func (m *runSpotEC2ConnMock) CreateTags(req *ec2.CreateTagsInput) (*ec2.CreateTa } } -func TestRun(t *testing.T) { - instanceId := aws.String("test-instance-id") - spotRequestId := aws.String("spot-id") - volumeId := aws.String("volume-id") +func defaultEc2Mock(instanceId, spotRequestId, volumeId *string) *runSpotEC2ConnMock { instance := &ec2.Instance{ InstanceId: instanceId, SpotInstanceRequestId: spotRequestId, @@ -204,7 +202,7 @@ func TestRun(t *testing.T) { }, }, } - ec2Mock := &runSpotEC2ConnMock{ + return &runSpotEC2ConnMock{ CreateLaunchTemplateFn: func(in *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) { return &ec2.CreateLaunchTemplateOutput{ LaunchTemplate: nil, @@ -233,6 +231,13 @@ func TestRun(t *testing.T) { }, nil }, } +} + +func TestRun(t *testing.T) { + instanceId := aws.String("test-instance-id") + spotRequestId := aws.String("spot-id") + volumeId := aws.String("volume-id") + ec2Mock := defaultEc2Mock(instanceId, spotRequestId, volumeId) uiMock := packer.TestUi(t) @@ -240,7 +245,6 @@ func TestRun(t *testing.T) { state.Put("ec2", ec2Mock) state.Put("ui", uiMock) state.Put("source_image", testImage()) - state.Put("region", "test-region") stepRunSpotInstance := getBasicStep() stepRunSpotInstance.Tags["Name"] = "Packer Builder" @@ -274,17 +278,13 @@ func TestRun(t *testing.T) { if *ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].ResourceType != "launch-template" { t.Fatalf("resource type 'launch-template' expected") } - if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags) != 2 { - t.Fatalf("2 tags expected") + if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags) != 1 { + t.Fatalf("1 launch template tag expected") } nameTag := ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags[0] - if *nameTag.Key != "Name" || *nameTag.Value != "Packer Builder" { - t.Fatalf("expected name tag") - } - testTag := ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags[1] - if *testTag.Key != "test-tag" || *testTag.Value != "test-value" { - t.Fatalf("expected test tag") + if *nameTag.Key != "spot-tag" || *nameTag.Value != "spot-tag-value" { + t.Fatalf("expected spot-tag: spot-tag-value") } if len(ec2Mock.CreateFleetParams) != 1 { @@ -324,3 +324,39 @@ func TestRun(t *testing.T) { t.Fatalf("should create tags for volume") } } + +func TestRun_NoSpotTags(t *testing.T) { + instanceId := aws.String("test-instance-id") + spotRequestId := aws.String("spot-id") + volumeId := aws.String("volume-id") + ec2Mock := defaultEc2Mock(instanceId, spotRequestId, volumeId) + + uiMock := packer.TestUi(t) + + state := tStateSpot() + state.Put("ec2", ec2Mock) + state.Put("ui", uiMock) + state.Put("source_image", testImage()) + + stepRunSpotInstance := getBasicStep() + stepRunSpotInstance.Tags["Name"] = "Packer Builder" + stepRunSpotInstance.Tags["test-tag"] = "test-value" + stepRunSpotInstance.VolumeTags = map[string]string{ + "volume-tag": "volume-tag-value", + } + + ctx := context.TODO() + action := stepRunSpotInstance.Run(ctx, state) + + if err := state.Get("error"); err != nil { + t.Fatalf("should not error, but: %v", err) + } + + if action != multistep.ActionContinue { + t.Fatalf("shoul continue, but: %v", action) + } + + if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications) != 0 { + t.Fatalf("0 launch template tags expected") + } +} diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 8c4f00fe2..03c8d0c03 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -164,7 +164,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) - state.Put("region", *ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step @@ -182,6 +181,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack ExpectedRootDevice: "ebs", InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior, InstanceType: b.config.InstanceType, + Region: *ec2conn.Config.Region, SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotTags: b.config.SpotTags, diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index 6600850f6..5688193a8 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -187,7 +187,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) - state.Put("region", *ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step @@ -205,6 +204,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack ExpectedRootDevice: "ebs", InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior, InstanceType: b.config.InstanceType, + Region: *ec2conn.Config.Region, SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotInstanceTypes: b.config.SpotInstanceTypes, diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index f9cb3b819..2c7a859a3 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -168,7 +168,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("iam", iam) state.Put("hook", hook) state.Put("ui", ui) - state.Put("region", *ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step @@ -186,6 +185,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack ExpectedRootDevice: "ebs", InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior, InstanceType: b.config.InstanceType, + Region: *ec2conn.Config.Region, SourceAMI: b.config.SourceAmi, SpotInstanceTypes: b.config.SpotInstanceTypes, SpotPrice: b.config.SpotPrice, diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 214f16283..fe755edb1 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -250,7 +250,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) - state.Put("region", ec2conn.Config.Region) generatedData := &builder.GeneratedData{State: state} var instanceStep multistep.Step @@ -266,6 +265,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Debug: b.config.PackerDebug, EbsOptimized: b.config.EbsOptimized, InstanceType: b.config.InstanceType, + Region: *ec2conn.Config.Region, SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotInstanceTypes: b.config.SpotInstanceTypes, From 7cb8af14413d9806062a52c16f79f661258b3f9f Mon Sep 17 00:00:00 2001 From: Aleksandr Serbin Date: Tue, 3 Nov 2020 22:28:19 +0100 Subject: [PATCH 3/3] amazon: remove region from state for chroot builder --- builder/amazon/chroot/builder.go | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index 1af8156c6..9fb431583 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -368,7 +368,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("awsSession", session) state.Put("hook", hook) state.Put("ui", ui) - state.Put("region", *ec2conn.Config.Region) state.Put("wrappedCommand", common.CommandWrapper(wrappedCommand)) generatedData := &builder.GeneratedData{State: state}