Merge pull request #2212 from mitchellh/f-amazon-add-tags-to-snapshots
Add EBS snapshot tags #846 #1219
This commit is contained in:
commit
2372393f64
|
@ -25,19 +25,56 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
|
|||
var ec2Tags []*ec2.Tag
|
||||
for key, value := range s.Tags {
|
||||
ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"", key, value))
|
||||
ec2Tags = append(ec2Tags, &ec2.Tag{Key: &key, Value: &value})
|
||||
ec2Tags = append(ec2Tags, &ec2.Tag{
|
||||
Key: aws.String(key),
|
||||
Value: aws.String(value),
|
||||
})
|
||||
}
|
||||
|
||||
// Declare list of resources to tag
|
||||
resourceIds := []*string{&ami}
|
||||
|
||||
// Retrieve image list for given AMI
|
||||
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
|
||||
ImageIDs: resourceIds,
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if len(imageResp.Images) == 0 {
|
||||
err := fmt.Errorf("Error retrieving details for AMI (%s), no images found", ami)
|
||||
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.BlockDeviceMappings {
|
||||
if device.EBS != nil && device.EBS.SnapshotID != nil {
|
||||
ui.Say(fmt.Sprintf("Tagging snapshot: %s", *device.EBS.SnapshotID))
|
||||
resourceIds = append(resourceIds, device.EBS.SnapshotID)
|
||||
}
|
||||
}
|
||||
|
||||
regionconn := ec2.New(&aws.Config{
|
||||
Credentials: ec2conn.Config.Credentials,
|
||||
Region: region,
|
||||
})
|
||||
_, err := regionconn.CreateTags(&ec2.CreateTagsInput{
|
||||
Resources: []*string{&ami},
|
||||
|
||||
_, err = regionconn.CreateTags(&ec2.CreateTagsInput{
|
||||
Resources: resourceIds,
|
||||
Tags: ec2Tags,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error adding tags to AMI (%s): %s", ami, err)
|
||||
err := fmt.Errorf("Error adding tags to Resources (%#v): %s", resourceIds, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package ebs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/mitchellh/packer/builder/amazon/common"
|
||||
builderT "github.com/mitchellh/packer/helper/builder/testing"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
func TestBuilderTagsAcc_basic(t *testing.T) {
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Builder: &Builder{},
|
||||
Template: testBuilderTagsAccBasic,
|
||||
Check: checkTags(),
|
||||
})
|
||||
}
|
||||
|
||||
func checkTags() builderT.TestCheckFunc {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
|
||||
tags := make(map[string]string)
|
||||
tags["OS_Version"] = "Ubuntu"
|
||||
tags["Release"] = "Latest"
|
||||
|
||||
// Get the actual *Artifact pointer so we can access the AMIs directly
|
||||
artifactRaw := artifacts[0]
|
||||
artifact, ok := artifactRaw.(*common.Artifact)
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown artifact: %#v", artifactRaw)
|
||||
}
|
||||
|
||||
// describe the image, get block devices with a snapshot
|
||||
ec2conn, _ := testEC2Conn()
|
||||
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
|
||||
ImageIDs: []*string{aws.String(artifact.Amis["us-east-1"])},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving details for AMI Artifcat (%#v) in Tags Test: %s", artifact, err)
|
||||
}
|
||||
|
||||
if len(imageResp.Images) == 0 {
|
||||
return fmt.Errorf("No images found for AMI Artifcat (%#v) in Tags Test: %s", artifact, err)
|
||||
}
|
||||
|
||||
image := imageResp.Images[0]
|
||||
|
||||
// Check only those with a Snapshot ID, i.e. not Ephemeral
|
||||
var snapshots []*string
|
||||
for _, device := range image.BlockDeviceMappings {
|
||||
if device.EBS != nil && device.EBS.SnapshotID != nil {
|
||||
snapshots = append(snapshots, device.EBS.SnapshotID)
|
||||
}
|
||||
}
|
||||
|
||||
// grab matching snapshot info
|
||||
resp, err := ec2conn.DescribeSnapshots(&ec2.DescribeSnapshotsInput{
|
||||
SnapshotIDs: snapshots,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retreiving Snapshots for AMI Artifcat (%#v) in Tags Test: %s", artifact, err)
|
||||
}
|
||||
|
||||
if len(resp.Snapshots) == 0 {
|
||||
return fmt.Errorf("No Snapshots found for AMI Artifcat (%#v) in Tags Test", artifact)
|
||||
}
|
||||
|
||||
// grab the snapshots, check the tags
|
||||
for _, s := range resp.Snapshots {
|
||||
expected := len(tags)
|
||||
for _, t := range s.Tags {
|
||||
for key, value := range tags {
|
||||
if key == *t.Key && value == *t.Value {
|
||||
expected--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if expected > 0 {
|
||||
return fmt.Errorf("Not all tags found")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
const testBuilderTagsAccBasic = `
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "test",
|
||||
"region": "us-east-1",
|
||||
"source_ami": "ami-9eaa1cf6",
|
||||
"instance_type": "t2.micro",
|
||||
"ssh_username": "ubuntu",
|
||||
"ami_name": "packer-tags-testing-{{timestamp}}",
|
||||
"tags": {
|
||||
"OS_Version": "Ubuntu",
|
||||
"Release": "Latest"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
|
@ -1,36 +0,0 @@
|
|||
#!/usr/bin/env bats
|
||||
#
|
||||
# This tests the amazon-ebs builder. The teardown function will automatically
|
||||
# delete any AMIs with a tag of `packer-test` being equal to "true" so
|
||||
# be sure any test cases set this.
|
||||
|
||||
load test_helper
|
||||
fixtures amazon-ebs
|
||||
|
||||
# This counts how many AMIs were copied to another region
|
||||
aws_ami_region_copy_count() {
|
||||
aws ec2 describe-images --region $1 --owners self --output text \
|
||||
--filters 'Name=tag:packer-id,Values=ami_region_copy' \
|
||||
--query "Images[*].ImageId" \
|
||||
| wc -l
|
||||
}
|
||||
|
||||
teardown() {
|
||||
aws_ami_cleanup 'us-east-1'
|
||||
aws_ami_cleanup 'us-west-1'
|
||||
aws_ami_cleanup 'us-west-2'
|
||||
}
|
||||
|
||||
@test "amazon-ebs: build minimal.json" {
|
||||
run packer build $FIXTURE_ROOT/minimal.json
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
# @unit-testable
|
||||
@test "amazon-ebs: AMI region copy" {
|
||||
run packer build $FIXTURE_ROOT/ami_region_copy.json
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(aws_ami_region_copy_count 'us-east-1')" -eq "1" ]
|
||||
[ "$(aws_ami_region_copy_count 'us-west-1')" -eq "1" ]
|
||||
[ "$(aws_ami_region_copy_count 'us-west-2')" -eq "1" ]
|
||||
}
|
|
@ -150,7 +150,8 @@ AMI if one with the same name already exists. Default `false`.
|
|||
"subnet-12345def", where Packer will launch the EC2 instance. This field is
|
||||
required if you are using an non-default VPC.
|
||||
|
||||
* `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.
|
||||
|
|
Loading…
Reference in New Issue