Merge pull request #8393 from hashicorp/fix_8362

Add no_ephemeral template option to nuke ephemeral drives from launch mappings
This commit is contained in:
Megan Marsh 2019-11-21 16:08:50 -08:00 committed by GitHub
commit 59e6e1d4d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 1 deletions

View File

@ -35,6 +35,7 @@ type StepRunSourceInstance struct {
UserData string UserData string
UserDataFile string UserDataFile string
VolumeTags TagMap VolumeTags TagMap
NoEphemeral bool
instanceId string instanceId string
} }
@ -116,6 +117,25 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
EbsOptimized: &s.EbsOptimized, 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 _, letter := range DefaultEphemeralDeviceLetters {
bd := &ec2.BlockDeviceMapping{
DeviceName: aws.String("xvdc" + string(letter)),
NoDevice: aws.String(""),
}
runOpts.BlockDeviceMappings = append(runOpts.BlockDeviceMappings, bd)
}
}
if s.EnableT2Unlimited { if s.EnableT2Unlimited {
creditOption := "unlimited" creditOption := "unlimited"
runOpts.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: &creditOption} runOpts.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: &creditOption}

View File

@ -41,12 +41,32 @@ type StepRunSpotInstance struct {
UserData string UserData string
UserDataFile string UserDataFile string
Ctx interpolate.Context Ctx interpolate.Context
NoEphemeral bool
instanceId string instanceId string
} }
func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string, func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string,
state multistep.StateBag, marketOptions *ec2.LaunchTemplateInstanceMarketOptionsRequest) *ec2.RequestLaunchTemplateData { 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 // Convert the BlockDeviceMapping into a
// LaunchTemplateBlockDeviceMappingRequest. These structs are identical, // LaunchTemplateBlockDeviceMappingRequest. These structs are identical,
// except for the EBS field -- on one, that field contains a // 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 // LaunchTemplateEbsBlockDeviceRequest structs are themselves
// identical except for the struct's name, so you can cast one directly // identical except for the struct's name, so you can cast one directly
// into the other. // into the other.
blockDeviceMappings := s.LaunchMappings.BuildEC2BlockDeviceMappings()
var launchMappingRequests []*ec2.LaunchTemplateBlockDeviceMappingRequest var launchMappingRequests []*ec2.LaunchTemplateBlockDeviceMappingRequest
for _, mapping := range blockDeviceMappings { for _, mapping := range blockDeviceMappings {
launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{ launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{

View File

@ -53,6 +53,16 @@ type Config struct {
// engine](/docs/templates/engine.html), see [Build template // engine](/docs/templates/engine.html), see [Build template
// data](#build-template-data) for more information. // data](#build-template-data) for more information.
VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"` VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"`
// 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 ctx interpolate.Context
} }
@ -162,6 +172,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
VolumeTags: b.config.VolumeRunTags, VolumeTags: b.config.VolumeRunTags,
NoEphemeral: b.config.NoEphemeral,
} }
} else { } else {
instanceStep = &awscommon.StepRunSourceInstance{ instanceStep = &awscommon.StepRunSourceInstance{
@ -181,6 +192,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
VolumeTags: b.config.VolumeRunTags, VolumeTags: b.config.VolumeRunTags,
NoEphemeral: b.config.NoEphemeral,
} }
} }

View File

@ -120,6 +120,7 @@ type FlatConfig struct {
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"` 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"` 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"` 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. // 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())}}, "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())}}, "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}, "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 return s
} }

View File

@ -22,3 +22,13 @@
engine](/docs/templates/engine.html), see [Build template engine](/docs/templates/engine.html), see [Build template
data](#build-template-data) for more information. data](#build-template-data) for more information.
- `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.