From 361e859556ace480bf6dcec922ac0a0662b6388e Mon Sep 17 00:00:00 2001 From: Ash Caire Date: Sun, 1 Mar 2015 10:20:37 +1100 Subject: [PATCH] Add EBS snapshot tags --- builder/amazon/common/step_create_tags.go | 25 +++++++++++++++++-- test/builder_amazon_ebs.bats | 18 +++++++++++++ .../amazon-ebs/ami_snapshot_tags.json | 20 +++++++++++++++ .../docs/builders/amazon-ebs.html.markdown | 3 ++- 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/amazon-ebs/ami_snapshot_tags.json diff --git a/builder/amazon/common/step_create_tags.go b/builder/amazon/common/step_create_tags.go index a204ca321..1d8b80ca7 100644 --- a/builder/amazon/common/step_create_tags.go +++ b/builder/amazon/common/step_create_tags.go @@ -19,7 +19,28 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction { if len(s.Tags) > 0 { for region, ami := range amis { - ui.Say(fmt.Sprintf("Adding tags to AMI (%s)...", ami)) + ui.Say(fmt.Sprintf("Preparing tags for AMI (%s) and related snapshots", ami)) + + // Declare list of resources to tag + resourceIds := []string{ami} + + // Retrieve image list for given AMI + imageResp, err := ec2conn.Images([]string{ami}, ec2.NewFilter()) + if err != nil { + err := fmt.Errorf("Error retrieving details for AMI (%s): %s", ami, err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + image := &imageResp.Images[0] + + // Add only those with a Snapshot ID, i.e. not Ephemeral + for _, device := range image.BlockDevices { + if device.SnapshotId != "" { + ui.Say(fmt.Sprintf("Tagging snapshot: %s", device.SnapshotId)) + resourceIds = append(resourceIds, device.SnapshotId) + } + } var ec2Tags []ec2.Tag for key, value := range s.Tags { @@ -28,7 +49,7 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction { } regionconn := ec2.New(ec2conn.Auth, aws.Regions[region]) - _, err := regionconn.CreateTags([]string{ami}, ec2Tags) + _, err = regionconn.CreateTags(resourceIds, ec2Tags) if err != nil { err := fmt.Errorf("Error adding tags to AMI (%s): %s", ami, err) state.Put("error", err) diff --git a/test/builder_amazon_ebs.bats b/test/builder_amazon_ebs.bats index 7dd17acbd..89f32a4a0 100755 --- a/test/builder_amazon_ebs.bats +++ b/test/builder_amazon_ebs.bats @@ -15,6 +15,18 @@ aws_ami_region_copy_count() { | wc -l } +# This verifies AMI tags are correctly applied to relevant snapshots +aws_ami_snapshot_tags_count() { + filter='Name=tag:packer-id,Values=ami_snapshot_tags' + aws ec2 describe-images --region $1 --owners self --output text \ + --filters "$filter" \ + --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId" \ + | aws ec2 describe-snapshots --region $1 --owners self --output text \ + --filters "$filter" \ + --snapshot-ids \ + | wc -l +} + teardown() { aws_ami_cleanup 'us-east-1' aws_ami_cleanup 'us-west-1' @@ -34,3 +46,9 @@ teardown() { [ "$(aws_ami_region_copy_count 'us-west-1')" -eq "1" ] [ "$(aws_ami_region_copy_count 'us-west-2')" -eq "1" ] } + +@test "amazon-ebs: AMI snapshot tags" { + run packer build $FIXTURE_ROOT/ami_snapshot_tags.json + [ "$status" -eq 0 ] + [ "$(aws_ami_snapshot_tags)" -eq "2" ] +} diff --git a/test/fixtures/amazon-ebs/ami_snapshot_tags.json b/test/fixtures/amazon-ebs/ami_snapshot_tags.json new file mode 100644 index 000000000..278474a32 --- /dev/null +++ b/test/fixtures/amazon-ebs/ami_snapshot_tags.json @@ -0,0 +1,20 @@ +{ + "builders": [{ + "type": "amazon-ebs", + "ami_name": "packer-test {{timestamp}}", + "instance_type": "m1.small", + "region": "us-east-1", + "ssh_username": "ubuntu", + "source_ami": "ami-0568456c", + "tags": { + "packer-test": "true", + "packer-id": "ami_snapshot_tags" + }, + "ami_block_device_mappings": [ + { + "device_name": "/dev/sde", + "volume_type": "standard" + } + ] + }] +} diff --git a/website/source/docs/builders/amazon-ebs.html.markdown b/website/source/docs/builders/amazon-ebs.html.markdown index 5e2c31e90..946b18eb9 100644 --- a/website/source/docs/builders/amazon-ebs.html.markdown +++ b/website/source/docs/builders/amazon-ebs.html.markdown @@ -146,7 +146,8 @@ each category, the available configuration keys are alphabetized. * `subnet_id` (string) - If using VPC, the ID of the subnet, such as "subnet-12345def", where Packer will launch the EC2 instance. -* `tags` (object of key/value strings) - Tags applied to the AMI. +* `tags` (object of key/value strings) - Tags applied to the AMI and + relevant snapshots. * `temporary_key_pair_name` (string) - The name of the temporary keypair to generate. By default, Packer generates a name with a UUID.