build/amazon-ebssurrogate: Add region copy, attributes, tags steps

As pointed out in the initial code review of #4351, some of the steps
from the standard EBS builder were (intetionally) omitted. It turns out
that these actually are useful, and the original rationale for the
omission was wrong. Consequently, this commit adds in the following
steps:

- `StepPrevalidate`
- `StepTagEBSVolumes`
- `StepDeregisterAMI`
- `StepCreateEncryptedAMICopy`
- `StepAMIRegionCopy`
- `StepModifyAMIAttribute`
- `StepCreateTags`

We also fix the interpolation filter and documentation to reflect these
additions, though the majority were already documented and just not
functional.
pull/4601/head
James Nugent 9 years ago
parent cc6abb0fc7
commit e856339309

@ -1,21 +1,20 @@
package ebs
package common
import (
"fmt"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/builder/amazon/common"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type stepTagEBSVolumes struct {
type StepTagEBSVolumes struct {
VolumeRunTags map[string]string
Ctx interpolate.Context
}
func (s *stepTagEBSVolumes) Run(state multistep.StateBag) multistep.StepAction {
func (s *StepTagEBSVolumes) Run(state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
instance := state.Get("instance").(*ec2.Instance)
sourceAMI := state.Get("source_image").(*ec2.Image)
@ -37,7 +36,7 @@ func (s *stepTagEBSVolumes) Run(state multistep.StateBag) multistep.StepAction {
}
ui.Say("Adding tags to source EBS Volumes")
tags, err := common.ConvertToEC2Tags(s.VolumeRunTags, *ec2conn.Config.Region, *sourceAMI.ImageId, s.Ctx)
tags, err := ConvertToEC2Tags(s.VolumeRunTags, *ec2conn.Config.Region, *sourceAMI.ImageId, s.Ctx)
if err != nil {
err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err)
state.Put("error", err)
@ -59,6 +58,6 @@ func (s *stepTagEBSVolumes) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionContinue
}
func (s *stepTagEBSVolumes) Cleanup(state multistep.StateBag) {
func (s *StepTagEBSVolumes) Cleanup(state multistep.StateBag) {
// No cleanup...
}

@ -149,7 +149,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Ctx: b.config.ctx,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
},
&stepTagEBSVolumes{
&awscommon.StepTagEBSVolumes{
VolumeRunTags: b.config.VolumeRunTags,
Ctx: b.config.ctx,
},

@ -28,7 +28,8 @@ type Config struct {
awscommon.BlockDevices `mapstructure:",squash"`
awscommon.AMIConfig `mapstructure:",squash"`
RootDevice RootBlockDevice `mapstructure:"ami_root_device"`
RootDevice RootBlockDevice `mapstructure:"ami_root_device"`
VolumeRunTags map[string]string `mapstructure:"run_volume_tags"`
ctx interpolate.Context
}
@ -47,6 +48,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
Exclude: []string{
"ami_description",
"run_tags",
"run_volume_tags",
"snapshot_tags",
"tags",
},
},
@ -119,6 +122,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
// Build the steps
steps := []multistep.Step{
&awscommon.StepPreValidate{
DestAmiName: b.config.AMIName,
ForceDeregister: b.config.AMIForceDeregister,
},
&awscommon.StepSourceAMIInfo{
SourceAmi: b.config.SourceAmi,
EnhancedNetworking: b.config.AMIEnhancedNetworking,
@ -155,6 +162,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Tags: b.config.RunTags,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
},
&awscommon.StepTagEBSVolumes{
VolumeRunTags: b.config.VolumeRunTags,
Ctx: b.config.ctx,
},
&awscommon.StepGetPassword{
Debug: b.config.PackerDebug,
Comm: &b.config.RunConfig.Comm,
@ -181,10 +192,39 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&StepSnapshotNewRootVolume{
NewRootMountPoint: b.config.RootDevice.SourceDeviceName,
},
&awscommon.StepDeregisterAMI{
ForceDeregister: b.config.AMIForceDeregister,
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
AMIName: b.config.AMIName,
},
&StepRegisterAMI{
RootDevice: b.config.RootDevice,
BlockDevices: b.config.BlockDevices.BuildLaunchDevices(),
},
&awscommon.StepCreateEncryptedAMICopy{
KeyID: b.config.AMIKmsKeyId,
EncryptBootVolume: b.config.AMIEncryptBootVolume,
Name: b.config.AMIName,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
Regions: b.config.AMIRegions,
Name: b.config.AMIName,
},
&awscommon.StepModifyAMIAttributes{
Description: b.config.AMIDescription,
Users: b.config.AMIUsers,
Groups: b.config.AMIGroups,
ProductCodes: b.config.AMIProductCodes,
SnapshotUsers: b.config.SnapshotUsers,
SnapshotGroups: b.config.SnapshotGroups,
Ctx: b.config.ctx,
},
&awscommon.StepCreateTags{
Tags: b.config.AMITags,
SnapshotTags: b.config.SnapshotTags,
Ctx: b.config.ctx,
},
}
// Run!

@ -14,6 +14,7 @@ import (
type StepRegisterAMI struct {
RootDevice RootBlockDevice
BlockDevices []*ec2.BlockDeviceMapping
image *ec2.Image
}
func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
@ -74,7 +75,45 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
imagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{registerResp.ImageId}})
if err != nil {
err := fmt.Errorf("Error searching for AMI: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.image = imagesResp.Images[0]
snapshots := make(map[string][]string)
for _, blockDeviceMapping := range imagesResp.Images[0].BlockDeviceMappings {
if blockDeviceMapping.Ebs != nil && blockDeviceMapping.Ebs.SnapshotId != nil {
snapshots[*ec2conn.Config.Region] = append(snapshots[*ec2conn.Config.Region], *blockDeviceMapping.Ebs.SnapshotId)
}
}
state.Put("snapshots", snapshots)
return multistep.ActionContinue
}
func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {}
func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {
if s.image == nil {
return
}
_, cancelled := state.GetOk(multistep.StateCancelled)
_, halted := state.GetOk(multistep.StateHalted)
if !cancelled && !halted {
return
}
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
ui.Say("Deregistering the AMI because cancelation or error...")
deregisterOpts := &ec2.DeregisterImageInput{ImageId: s.image.ImageId}
if _, err := ec2conn.DeregisterImage(deregisterOpts); err != nil {
ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %s", err))
return
}
}

@ -163,6 +163,14 @@ builder.
- `force_delete_snapshot` (boolean) - Force Packer to delete snapshots associated with
AMIs, which have been deregistered by `force_deregister`. Default `false`.
- `encrypt_boot` (boolean) - Instruct packer to automatically create a copy of the
AMI with an encrypted boot volume (discarding the initial unencrypted AMI in the
process). Default `false`.
- `kms_key_id` (string) - The ID of the KMS key to use for boot volume encryption.
This only applies to the main `region`, other regions where the AMI will be copied
will be encrypted by the default EBS KMS key.
- `iam_instance_profile` (string) - The name of an [IAM instance
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
to launch the EC2 instance with.

Loading…
Cancel
Save