From 0e2bdc8be6852280ce9d7a5c86e5548555530d1b Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Tue, 19 Nov 2019 11:52:18 -0800 Subject: [PATCH 1/4] forcibly prevent ephemeral drives from being created in the amazon-ebs builder, when no_ephemeral is set --- .../amazon/common/step_run_source_instance.go | 21 +++++++++++++++++++ builder/amazon/ebs/builder.go | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index ed0cefe53..008355330 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -35,6 +35,7 @@ type StepRunSourceInstance struct { UserData string UserDataFile string VolumeTags TagMap + NoEphemeral bool instanceId string } @@ -116,6 +117,26 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa EbsOptimized: &s.EbsOptimized, } + if s.NoEphemeral { + // This is only relevant for windows guests. Ephemeral drives by + // default are assigned to drive names xvdca-xvdcz. + // When vms are launched from the AWS console, they're automatically + // removed from the block devices if the user hasn't said to use them, + // but the SDK does not perform this cleanup. The following code just + // manually removes the ephemeral drives from the mapping so that they + // don't clutter up console views and cause confusion. + log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings") + DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz" + for i := 0; i < len(DefaultEphemeralDeviceLetters); i++ { + + bd := &ec2.BlockDeviceMapping{ + DeviceName: aws.String("xvdc" + string(DefaultEphemeralDeviceLetters[i])), + NoDevice: aws.String(""), + } + runOpts.BlockDeviceMappings = append(runOpts.BlockDeviceMappings, bd) + } + } + if s.EnableT2Unlimited { creditOption := "unlimited" runOpts.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: &creditOption} diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index ab9f8a0e2..075ad4621 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -53,6 +53,12 @@ type Config struct { // engine](/docs/templates/engine.html), see [Build template // data](#build-template-data) for more information. VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"` + // If you set this flag, we'll add clauses to the + // launch_block_device_mappings that make sure ephemeral drives don't show + // up in the EC2 console. If you launched from the EC2 console, you'd get + // this automatically, but the SDK does not provide this service. + // This only applies when you are not running spot instances. + NoEphemeral bool `mapstructure:"no_ephemeral" required:"false"` ctx interpolate.Context } @@ -181,6 +187,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack UserData: b.config.UserData, UserDataFile: b.config.UserDataFile, VolumeTags: b.config.VolumeRunTags, + NoEphemeral: b.config.NoEphemeral, } } From 08e97ba4d8540678fe6361522cb227a4908fa495 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Wed, 20 Nov 2019 13:49:04 -0800 Subject: [PATCH 2/4] generate code for no_ephemeral option --- builder/amazon/ebs/builder.hcl2spec.go | 2 ++ .../builder/amazon/ebs/_Config-not-required.html.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/builder/amazon/ebs/builder.hcl2spec.go b/builder/amazon/ebs/builder.hcl2spec.go index e0556b568..231368838 100644 --- a/builder/amazon/ebs/builder.hcl2spec.go +++ b/builder/amazon/ebs/builder.hcl2spec.go @@ -120,6 +120,7 @@ type FlatConfig struct { AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"` LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"` VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"` + NoEphemeral *bool `mapstructure:"no_ephemeral" required:"false" cty:"no_ephemeral"` } // FlatMapstructure returns a new FlatConfig. @@ -241,6 +242,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: &hcldec.BlockSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())}}, "launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: &hcldec.BlockSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())}}, "run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false}, + "no_ephemeral": &hcldec.AttrSpec{Name: "no_ephemeral", Type: cty.Bool, Required: false}, } return s } diff --git a/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md b/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md index d49d105c5..63e1edafb 100644 --- a/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md +++ b/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md @@ -21,4 +21,10 @@ duplicated in `tags`. This is a [template engine](/docs/templates/engine.html), see [Build template data](#build-template-data) for more information. + +- `no_ephemeral` (bool) - If you set this flag, we'll add clauses to the + launch_block_device_mappings that make sure ephemeral drives don't show + up in the EC2 console. If you launched from the EC2 console, you'd get + this automatically, but the SDK does not provide this service. + This only applies when you are not running spot instances. \ No newline at end of file From 67c337310764d2ea40080cf42db29fa33aaeeae4 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Thu, 21 Nov 2019 12:46:31 -0800 Subject: [PATCH 3/4] enable no_ephemeral for spot devices, clean up ranging behavior, update docs --- .../amazon/common/step_run_source_instance.go | 5 ++--- .../amazon/common/step_run_spot_instance.go | 21 ++++++++++++++++++- builder/amazon/ebs/builder.go | 14 ++++++++----- .../amazon/ebs/_Config-not-required.html.md | 14 ++++++++----- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index 008355330..f55c2d04d 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -127,10 +127,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa // don't clutter up console views and cause confusion. log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings") DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz" - for i := 0; i < len(DefaultEphemeralDeviceLetters); i++ { - + for _, letter := range DefaultEphemeralDeviceLetters { bd := &ec2.BlockDeviceMapping{ - DeviceName: aws.String("xvdc" + string(DefaultEphemeralDeviceLetters[i])), + DeviceName: aws.String("xvdc" + string(letter)), NoDevice: aws.String(""), } runOpts.BlockDeviceMappings = append(runOpts.BlockDeviceMappings, bd) diff --git a/builder/amazon/common/step_run_spot_instance.go b/builder/amazon/common/step_run_spot_instance.go index 8cb92baf2..06cb28912 100644 --- a/builder/amazon/common/step_run_spot_instance.go +++ b/builder/amazon/common/step_run_spot_instance.go @@ -41,12 +41,32 @@ type StepRunSpotInstance struct { UserData string UserDataFile string Ctx interpolate.Context + NoEphemeral bool instanceId string } func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string, state multistep.StateBag, marketOptions *ec2.LaunchTemplateInstanceMarketOptionsRequest) *ec2.RequestLaunchTemplateData { + blockDeviceMappings := s.LaunchMappings.BuildEC2BlockDeviceMappings() + if s.NoEphemeral { + // This is only relevant for windows guests. Ephemeral drives by + // default are assigned to drive names xvdca-xvdcz. + // When vms are launched from the AWS console, they're automatically + // removed from the block devices if the user hasn't said to use them, + // but the SDK does not perform this cleanup. The following code just + // manually removes the ephemeral drives from the mapping so that they + // don't clutter up console views and cause confusion. + log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings") + DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz" + for _, letter := range DefaultEphemeralDeviceLetters { + bd := &ec2.BlockDeviceMapping{ + DeviceName: aws.String("xvdc" + string(letter)), + NoDevice: aws.String(""), + } + blockDeviceMappings = append(blockDeviceMappings, bd) + } + } // Convert the BlockDeviceMapping into a // LaunchTemplateBlockDeviceMappingRequest. These structs are identical, // except for the EBS field -- on one, that field contains a @@ -55,7 +75,6 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string, // LaunchTemplateEbsBlockDeviceRequest structs are themselves // identical except for the struct's name, so you can cast one directly // into the other. - blockDeviceMappings := s.LaunchMappings.BuildEC2BlockDeviceMappings() var launchMappingRequests []*ec2.LaunchTemplateBlockDeviceMappingRequest for _, mapping := range blockDeviceMappings { launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{ diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 075ad4621..3e68124c5 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -53,11 +53,15 @@ type Config struct { // engine](/docs/templates/engine.html), see [Build template // data](#build-template-data) for more information. VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"` - // If you set this flag, we'll add clauses to the - // launch_block_device_mappings that make sure ephemeral drives don't show - // up in the EC2 console. If you launched from the EC2 console, you'd get - // this automatically, but the SDK does not provide this service. - // This only applies when you are not running spot instances. + // Relevant only to Windows guests: If you set this flag, we'll add clauses + // to the launch_block_device_mappings that make sure ephemeral drives + // don't show up in the EC2 console. If you launched from the EC2 console, + // you'd get this automatically, but the SDK does not provide this service. + // For more information, see + // https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/InstanceStorage.html. + // Because we don't validate the OS type of your guest, it is up to you to + // make sure you don't set this for *nix guests; behavior may be + // unpredictable. NoEphemeral bool `mapstructure:"no_ephemeral" required:"false"` ctx interpolate.Context diff --git a/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md b/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md index 63e1edafb..d12667551 100644 --- a/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md +++ b/website/source/partials/builder/amazon/ebs/_Config-not-required.html.md @@ -22,9 +22,13 @@ engine](/docs/templates/engine.html), see [Build template data](#build-template-data) for more information. -- `no_ephemeral` (bool) - If you set this flag, we'll add clauses to the - launch_block_device_mappings that make sure ephemeral drives don't show - up in the EC2 console. If you launched from the EC2 console, you'd get - this automatically, but the SDK does not provide this service. - This only applies when you are not running spot instances. +- `no_ephemeral` (bool) - Relevant only to Windows guests: If you set this flag, we'll add clauses + to the launch_block_device_mappings that make sure ephemeral drives + don't show up in the EC2 console. If you launched from the EC2 console, + you'd get this automatically, but the SDK does not provide this service. + For more information, see + https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/InstanceStorage.html. + Because we don't validate the OS type of your guest, it is up to you to + make sure you don't set this for *nix guests; behavior may be + unpredictable. \ No newline at end of file From 818d9bb087ab090c4c0a516f56f0a3324081435c Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Thu, 21 Nov 2019 13:21:56 -0800 Subject: [PATCH 4/4] send to step run spot instance --- builder/amazon/ebs/builder.go | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 3e68124c5..4c7c46ad5 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -172,6 +172,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack UserData: b.config.UserData, UserDataFile: b.config.UserDataFile, VolumeTags: b.config.VolumeRunTags, + NoEphemeral: b.config.NoEphemeral, } } else { instanceStep = &awscommon.StepRunSourceInstance{