diff --git a/builder/amazon/common/block_device.go b/builder/amazon/common/block_device.go index 9c6a2196b..06fda046b 100644 --- a/builder/amazon/common/block_device.go +++ b/builder/amazon/common/block_device.go @@ -21,6 +21,8 @@ type BlockDevice struct { VolumeType string `mapstructure:"volume_type"` VolumeSize int64 `mapstructure:"volume_size"` KmsKeyId string `mapstructure:"kms_key_id"` + // ebssurrogate only + OmitFromArtifact bool `mapstructure:"omit_from_artifact"` } type BlockDevices struct { @@ -96,6 +98,7 @@ func (b *BlockDevice) Prepare(ctx *interpolate.Context) error { return fmt.Errorf("The device %v, must also have `encrypted: "+ "true` when setting a kms_key_id.", b.DeviceName) } + return nil } @@ -120,3 +123,13 @@ func (b *AMIBlockDevices) BuildAMIDevices() []*ec2.BlockDeviceMapping { func (b *LaunchBlockDevices) BuildLaunchDevices() []*ec2.BlockDeviceMapping { return buildBlockDevices(b.LaunchMappings) } + +func (b *LaunchBlockDevices) GetOmissions() map[string]bool { + omitMap := make(map[string]bool) + + for _, blockDevice := range b.LaunchMappings { + omitMap[blockDevice.DeviceName] = blockDevice.OmitFromArtifact + } + + return omitMap +} diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index 6ea3bc9a7..6c6c6a130 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -79,6 +79,9 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { for _, launchDevice := range b.config.BlockDevices.LaunchMappings { if launchDevice.DeviceName == b.config.RootDevice.SourceDeviceName { foundRootVolume = true + if launchDevice.OmitFromArtifact { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("You cannot set \"omit_from_artifact\": \"true\" for the root volume.")) + } } } @@ -243,7 +246,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack EnableAMIENASupport: b.config.AMIENASupport, }, &StepSnapshotVolumes{ - LaunchDevices: launchDevices, + LaunchDevices: launchDevices, + SnapshotOmitMap: b.config.GetOmissions(), }, &awscommon.StepDeregisterAMI{ AccessConfig: &b.config.AccessConfig, @@ -259,6 +263,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack EnableAMISriovNetSupport: b.config.AMISriovNetSupport, EnableAMIENASupport: b.config.AMIENASupport, Architecture: b.config.Architecture, + LaunchOmitMap: b.config.GetOmissions(), }, &awscommon.StepAMIRegionCopy{ AccessConfig: &b.config.AccessConfig, diff --git a/builder/amazon/ebssurrogate/step_register_ami.go b/builder/amazon/ebssurrogate/step_register_ami.go index 13c98d864..743d17a1a 100644 --- a/builder/amazon/ebssurrogate/step_register_ami.go +++ b/builder/amazon/ebssurrogate/step_register_ami.go @@ -20,6 +20,7 @@ type StepRegisterAMI struct { EnableAMISriovNetSupport bool Architecture string image *ec2.Image + LaunchOmitMap map[string]bool } func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { @@ -126,6 +127,11 @@ func (s *StepRegisterAMI) combineDevices(snapshotIds map[string]string) []*ec2.B // the same name in ami_block_device_mappings, except for the // one designated as the root device in ami_root_device for _, device := range s.LaunchDevices { + // Skip devices we've flagged for omission + omit, ok := s.LaunchOmitMap[*device.DeviceName] + if ok && omit { + continue + } snapshotId, ok := snapshotIds[*device.DeviceName] if ok { device.Ebs.SnapshotId = aws.String(snapshotId) diff --git a/builder/amazon/ebssurrogate/step_snapshot_volumes.go b/builder/amazon/ebssurrogate/step_snapshot_volumes.go index f238815e1..f5b4602c0 100644 --- a/builder/amazon/ebssurrogate/step_snapshot_volumes.go +++ b/builder/amazon/ebssurrogate/step_snapshot_volumes.go @@ -18,8 +18,9 @@ import ( // Produces: // snapshot_ids map[string]string - IDs of the created snapshots type StepSnapshotVolumes struct { - LaunchDevices []*ec2.BlockDeviceMapping - snapshotIds map[string]string + LaunchDevices []*ec2.BlockDeviceMapping + snapshotIds map[string]string + SnapshotOmitMap map[string]bool } func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName string, state multistep.StateBag) error { @@ -64,6 +65,12 @@ func (s *StepSnapshotVolumes) Run(ctx context.Context, state multistep.StateBag) var wg sync.WaitGroup var errs *multierror.Error for _, device := range s.LaunchDevices { + // Skip devices we've flagged for omission + omit, ok := s.SnapshotOmitMap[*device.DeviceName] + if ok && omit { + continue + } + wg.Add(1) go func(device *ec2.BlockDeviceMapping) { defer wg.Done() diff --git a/website/source/docs/builders/amazon-ebssurrogate.html.md.erb b/website/source/docs/builders/amazon-ebssurrogate.html.md.erb index 56b3dddae..237c70383 100644 --- a/website/source/docs/builders/amazon-ebssurrogate.html.md.erb +++ b/website/source/docs/builders/amazon-ebssurrogate.html.md.erb @@ -252,6 +252,14 @@ builder. new AMI, the instance automatically launches with these additional volumes, and will restore them from snapshots taken from the source instance. + In addition to the fields available in ami_block_device_mappings, you may + optionally use the following field: + - "omit_from_artifact" (boolean) - If true, this block device will not + be snapshotted and the created AMI will not contain block device mapping + information for this volume. If false, the block device will be mapped + into the final created AMI. Set this option to true if you need a block + device mounted in the surrogate AMI but not in the final created AMI. + - `mfa_code` (string) - The MFA [TOTP](https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm) code. This should probably be a user variable since it changes all the