github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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  `