github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_ami_copy_test.go (about) 1 package aws 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/service/ec2" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/terraform" 14 ) 15 16 func TestAccAWSAMICopy(t *testing.T) { 17 var amiId string 18 snapshots := []string{} 19 20 resource.Test(t, resource.TestCase{ 21 PreCheck: func() { testAccPreCheck(t) }, 22 Providers: testAccProviders, 23 Steps: []resource.TestStep{ 24 resource.TestStep{ 25 Config: testAccAWSAMICopyConfig, 26 Check: func(state *terraform.State) error { 27 rs, ok := state.RootModule().Resources["aws_ami_copy.test"] 28 if !ok { 29 return fmt.Errorf("AMI resource not found") 30 } 31 32 amiId = rs.Primary.ID 33 34 if amiId == "" { 35 return fmt.Errorf("AMI id is not set") 36 } 37 38 conn := testAccProvider.Meta().(*AWSClient).ec2conn 39 req := &ec2.DescribeImagesInput{ 40 ImageIds: []*string{aws.String(amiId)}, 41 } 42 describe, err := conn.DescribeImages(req) 43 if err != nil { 44 return err 45 } 46 47 if len(describe.Images) != 1 || 48 *describe.Images[0].ImageId != rs.Primary.ID { 49 return fmt.Errorf("AMI not found") 50 } 51 52 image := describe.Images[0] 53 if expected := "available"; *image.State != expected { 54 return fmt.Errorf("invalid image state; expected %v, got %v", expected, image.State) 55 } 56 if expected := "machine"; *image.ImageType != expected { 57 return fmt.Errorf("wrong image type; expected %v, got %v", expected, image.ImageType) 58 } 59 if expected := "terraform-acc-ami-copy"; *image.Name != expected { 60 return fmt.Errorf("wrong name; expected %v, got %v", expected, image.Name) 61 } 62 63 for _, bdm := range image.BlockDeviceMappings { 64 // The snapshot ID might not be set, 65 // even for a block device that is an 66 // EBS volume. 67 if bdm.Ebs != nil && bdm.Ebs.SnapshotId != nil { 68 snapshots = append(snapshots, *bdm.Ebs.SnapshotId) 69 } 70 } 71 72 if expected := 1; len(snapshots) != expected { 73 return fmt.Errorf("wrong number of snapshots; expected %v, got %v", expected, len(snapshots)) 74 } 75 76 return nil 77 }, 78 }, 79 }, 80 CheckDestroy: func(state *terraform.State) error { 81 conn := testAccProvider.Meta().(*AWSClient).ec2conn 82 diReq := &ec2.DescribeImagesInput{ 83 ImageIds: []*string{aws.String(amiId)}, 84 } 85 diRes, err := conn.DescribeImages(diReq) 86 if err != nil { 87 return err 88 } 89 90 if len(diRes.Images) > 0 { 91 state := diRes.Images[0].State 92 return fmt.Errorf("AMI %v remains in state %v", amiId, state) 93 } 94 95 stillExist := make([]string, 0, len(snapshots)) 96 checkErrors := make(map[string]error) 97 for _, snapshotId := range snapshots { 98 dsReq := &ec2.DescribeSnapshotsInput{ 99 SnapshotIds: []*string{aws.String(snapshotId)}, 100 } 101 _, err := conn.DescribeSnapshots(dsReq) 102 if err == nil { 103 stillExist = append(stillExist, snapshotId) 104 continue 105 } 106 107 awsErr, ok := err.(awserr.Error) 108 if !ok { 109 checkErrors[snapshotId] = err 110 continue 111 } 112 113 if awsErr.Code() != "InvalidSnapshot.NotFound" { 114 checkErrors[snapshotId] = err 115 continue 116 } 117 } 118 119 if len(stillExist) > 0 || len(checkErrors) > 0 { 120 errParts := []string{ 121 "Expected all snapshots to be gone, but:", 122 } 123 for _, snapshotId := range stillExist { 124 errParts = append( 125 errParts, 126 fmt.Sprintf("- %v still exists", snapshotId), 127 ) 128 } 129 for snapshotId, err := range checkErrors { 130 errParts = append( 131 errParts, 132 fmt.Sprintf("- checking %v gave error: %v", snapshotId, err), 133 ) 134 } 135 return errors.New(strings.Join(errParts, "\n")) 136 } 137 138 return nil 139 }, 140 }) 141 } 142 143 var testAccAWSAMICopyConfig = ` 144 provider "aws" { 145 region = "us-east-1" 146 } 147 148 // An AMI can't be directly copied from one account to another, and 149 // we can't rely on any particular AMI being available since anyone 150 // can run this test in whatever account they like. 151 // Therefore we jump through some hoops here: 152 // - Spin up an EC2 instance based on a public AMI 153 // - Create an AMI by snapshotting that EC2 instance, using 154 // aws_ami_from_instance . 155 // - Copy the new AMI using aws_ami_copy . 156 // 157 // Thus this test can only succeed if the aws_ami_from_instance resource 158 // is working. If it's misbehaving it will likely cause this test to fail too. 159 160 // Since we're booting a t2.micro HVM instance we need a VPC for it to boot 161 // up into. 162 163 resource "aws_vpc" "foo" { 164 cidr_block = "10.1.0.0/16" 165 } 166 167 resource "aws_subnet" "foo" { 168 cidr_block = "10.1.1.0/24" 169 vpc_id = "${aws_vpc.foo.id}" 170 } 171 172 resource "aws_instance" "test" { 173 // This AMI has one block device mapping, so we expect to have 174 // one snapshot in our created AMI. 175 // This is an Ubuntu Linux HVM AMI. A public HVM AMI is required 176 // because paravirtual images cannot be copied between accounts. 177 ami = "ami-0f8bce65" 178 instance_type = "t2.micro" 179 tags { 180 Name = "terraform-acc-ami-copy-victim" 181 } 182 183 subnet_id = "${aws_subnet.foo.id}" 184 } 185 186 resource "aws_ami_from_instance" "test" { 187 name = "terraform-acc-ami-copy-victim" 188 description = "Testing Terraform aws_ami_from_instance resource" 189 source_instance_id = "${aws_instance.test.id}" 190 } 191 192 resource "aws_ami_copy" "test" { 193 name = "terraform-acc-ami-copy" 194 description = "Testing Terraform aws_ami_copy resource" 195 source_ami_id = "${aws_ami_from_instance.test.id}" 196 source_ami_region = "us-east-1" 197 } 198 `