github.com/ottenhoff/terraform@v0.7.0-rc1.0.20160607213102-ac2d195cc560/builtin/providers/aws/resource_aws_instance_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/aws/awserr"
    10  	"github.com/aws/aws-sdk-go/service/ec2"
    11  	"github.com/hashicorp/terraform/helper/resource"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  	"github.com/hashicorp/terraform/terraform"
    14  )
    15  
    16  func TestAccAWSInstance_basic(t *testing.T) {
    17  	var v ec2.Instance
    18  	var vol *ec2.Volume
    19  
    20  	testCheck := func(*terraform.State) error {
    21  		if *v.Placement.AvailabilityZone != "us-west-2a" {
    22  			return fmt.Errorf("bad availability zone: %#v", *v.Placement.AvailabilityZone)
    23  		}
    24  
    25  		if len(v.SecurityGroups) == 0 {
    26  			return fmt.Errorf("no security groups: %#v", v.SecurityGroups)
    27  		}
    28  		if *v.SecurityGroups[0].GroupName != "tf_test_foo" {
    29  			return fmt.Errorf("no security groups: %#v", v.SecurityGroups)
    30  		}
    31  
    32  		return nil
    33  	}
    34  
    35  	resource.Test(t, resource.TestCase{
    36  		PreCheck: func() { testAccPreCheck(t) },
    37  
    38  		// We ignore security groups because even with EC2 classic
    39  		// we'll import as VPC security groups, which is fine. We verify
    40  		// VPC security group import in other tests
    41  		IDRefreshName:   "aws_instance.foo",
    42  		IDRefreshIgnore: []string{"user_data", "security_groups", "vpc_security_group_ids"},
    43  
    44  		Providers:    testAccProviders,
    45  		CheckDestroy: testAccCheckInstanceDestroy,
    46  		Steps: []resource.TestStep{
    47  			// Create a volume to cover #1249
    48  			resource.TestStep{
    49  				// Need a resource in this config so the provisioner will be available
    50  				Config: testAccInstanceConfig_pre,
    51  				Check: func(*terraform.State) error {
    52  					conn := testAccProvider.Meta().(*AWSClient).ec2conn
    53  					var err error
    54  					vol, err = conn.CreateVolume(&ec2.CreateVolumeInput{
    55  						AvailabilityZone: aws.String("us-west-2a"),
    56  						Size:             aws.Int64(int64(5)),
    57  					})
    58  					return err
    59  				},
    60  			},
    61  
    62  			resource.TestStep{
    63  				Config: testAccInstanceConfig,
    64  				Check: resource.ComposeTestCheckFunc(
    65  					testAccCheckInstanceExists(
    66  						"aws_instance.foo", &v),
    67  					testCheck,
    68  					resource.TestCheckResourceAttr(
    69  						"aws_instance.foo",
    70  						"user_data",
    71  						"3dc39dda39be1205215e776bad998da361a5955d"),
    72  					resource.TestCheckResourceAttr(
    73  						"aws_instance.foo", "ebs_block_device.#", "0"),
    74  				),
    75  			},
    76  
    77  			// We repeat the exact same test so that we can be sure
    78  			// that the user data hash stuff is working without generating
    79  			// an incorrect diff.
    80  			resource.TestStep{
    81  				Config: testAccInstanceConfig,
    82  				Check: resource.ComposeTestCheckFunc(
    83  					testAccCheckInstanceExists(
    84  						"aws_instance.foo", &v),
    85  					testCheck,
    86  					resource.TestCheckResourceAttr(
    87  						"aws_instance.foo",
    88  						"user_data",
    89  						"3dc39dda39be1205215e776bad998da361a5955d"),
    90  					resource.TestCheckResourceAttr(
    91  						"aws_instance.foo", "ebs_block_device.#", "0"),
    92  				),
    93  			},
    94  
    95  			// Clean up volume created above
    96  			resource.TestStep{
    97  				Config: testAccInstanceConfig,
    98  				Check: func(*terraform.State) error {
    99  					conn := testAccProvider.Meta().(*AWSClient).ec2conn
   100  					_, err := conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: vol.VolumeId})
   101  					return err
   102  				},
   103  			},
   104  		},
   105  	})
   106  }
   107  
   108  func TestAccAWSInstance_blockDevices(t *testing.T) {
   109  	var v ec2.Instance
   110  
   111  	testCheck := func() resource.TestCheckFunc {
   112  		return func(*terraform.State) error {
   113  
   114  			// Map out the block devices by name, which should be unique.
   115  			blockDevices := make(map[string]*ec2.InstanceBlockDeviceMapping)
   116  			for _, blockDevice := range v.BlockDeviceMappings {
   117  				blockDevices[*blockDevice.DeviceName] = blockDevice
   118  			}
   119  
   120  			// Check if the root block device exists.
   121  			if _, ok := blockDevices["/dev/sda1"]; !ok {
   122  				return fmt.Errorf("block device doesn't exist: /dev/sda1")
   123  			}
   124  
   125  			// Check if the secondary block device exists.
   126  			if _, ok := blockDevices["/dev/sdb"]; !ok {
   127  				return fmt.Errorf("block device doesn't exist: /dev/sdb")
   128  			}
   129  
   130  			// Check if the third block device exists.
   131  			if _, ok := blockDevices["/dev/sdc"]; !ok {
   132  				return fmt.Errorf("block device doesn't exist: /dev/sdc")
   133  			}
   134  
   135  			// Check if the encrypted block device exists
   136  			if _, ok := blockDevices["/dev/sdd"]; !ok {
   137  				return fmt.Errorf("block device doesn't exist: /dev/sdd")
   138  			}
   139  
   140  			return nil
   141  		}
   142  	}
   143  
   144  	resource.Test(t, resource.TestCase{
   145  		PreCheck:      func() { testAccPreCheck(t) },
   146  		IDRefreshName: "aws_instance.foo",
   147  		IDRefreshIgnore: []string{
   148  			"ephemeral_block_device", "user_data", "security_groups", "vpc_security_groups"},
   149  		Providers:    testAccProviders,
   150  		CheckDestroy: testAccCheckInstanceDestroy,
   151  		Steps: []resource.TestStep{
   152  			resource.TestStep{
   153  				Config: testAccInstanceConfigBlockDevices,
   154  				Check: resource.ComposeTestCheckFunc(
   155  					testAccCheckInstanceExists(
   156  						"aws_instance.foo", &v),
   157  					resource.TestCheckResourceAttr(
   158  						"aws_instance.foo", "root_block_device.#", "1"),
   159  					resource.TestCheckResourceAttr(
   160  						"aws_instance.foo", "root_block_device.0.volume_size", "11"),
   161  					resource.TestCheckResourceAttr(
   162  						"aws_instance.foo", "root_block_device.0.volume_type", "gp2"),
   163  					resource.TestCheckResourceAttr(
   164  						"aws_instance.foo", "ebs_block_device.#", "3"),
   165  					resource.TestCheckResourceAttr(
   166  						"aws_instance.foo", "ebs_block_device.2576023345.device_name", "/dev/sdb"),
   167  					resource.TestCheckResourceAttr(
   168  						"aws_instance.foo", "ebs_block_device.2576023345.volume_size", "9"),
   169  					resource.TestCheckResourceAttr(
   170  						"aws_instance.foo", "ebs_block_device.2576023345.volume_type", "standard"),
   171  					resource.TestCheckResourceAttr(
   172  						"aws_instance.foo", "ebs_block_device.2554893574.device_name", "/dev/sdc"),
   173  					resource.TestCheckResourceAttr(
   174  						"aws_instance.foo", "ebs_block_device.2554893574.volume_size", "10"),
   175  					resource.TestCheckResourceAttr(
   176  						"aws_instance.foo", "ebs_block_device.2554893574.volume_type", "io1"),
   177  					resource.TestCheckResourceAttr(
   178  						"aws_instance.foo", "ebs_block_device.2554893574.iops", "100"),
   179  					resource.TestCheckResourceAttr(
   180  						"aws_instance.foo", "ebs_block_device.2634515331.device_name", "/dev/sdd"),
   181  					resource.TestCheckResourceAttr(
   182  						"aws_instance.foo", "ebs_block_device.2634515331.encrypted", "true"),
   183  					resource.TestCheckResourceAttr(
   184  						"aws_instance.foo", "ebs_block_device.2634515331.volume_size", "12"),
   185  					resource.TestCheckResourceAttr(
   186  						"aws_instance.foo", "ephemeral_block_device.#", "1"),
   187  					resource.TestCheckResourceAttr(
   188  						"aws_instance.foo", "ephemeral_block_device.1692014856.device_name", "/dev/sde"),
   189  					resource.TestCheckResourceAttr(
   190  						"aws_instance.foo", "ephemeral_block_device.1692014856.virtual_name", "ephemeral0"),
   191  					testCheck(),
   192  				),
   193  			},
   194  		},
   195  	})
   196  }
   197  
   198  func TestAccAWSInstance_sourceDestCheck(t *testing.T) {
   199  	var v ec2.Instance
   200  
   201  	testCheck := func(enabled bool) resource.TestCheckFunc {
   202  		return func(*terraform.State) error {
   203  			if v.SourceDestCheck == nil {
   204  				return fmt.Errorf("bad source_dest_check: got nil")
   205  			}
   206  			if *v.SourceDestCheck != enabled {
   207  				return fmt.Errorf("bad source_dest_check: %#v", *v.SourceDestCheck)
   208  			}
   209  
   210  			return nil
   211  		}
   212  	}
   213  
   214  	resource.Test(t, resource.TestCase{
   215  		PreCheck:      func() { testAccPreCheck(t) },
   216  		IDRefreshName: "aws_instance.foo",
   217  		Providers:     testAccProviders,
   218  		CheckDestroy:  testAccCheckInstanceDestroy,
   219  		Steps: []resource.TestStep{
   220  			resource.TestStep{
   221  				Config: testAccInstanceConfigSourceDestDisable,
   222  				Check: resource.ComposeTestCheckFunc(
   223  					testAccCheckInstanceExists("aws_instance.foo", &v),
   224  					testCheck(false),
   225  				),
   226  			},
   227  
   228  			resource.TestStep{
   229  				Config: testAccInstanceConfigSourceDestEnable,
   230  				Check: resource.ComposeTestCheckFunc(
   231  					testAccCheckInstanceExists("aws_instance.foo", &v),
   232  					testCheck(true),
   233  				),
   234  			},
   235  
   236  			resource.TestStep{
   237  				Config: testAccInstanceConfigSourceDestDisable,
   238  				Check: resource.ComposeTestCheckFunc(
   239  					testAccCheckInstanceExists("aws_instance.foo", &v),
   240  					testCheck(false),
   241  				),
   242  			},
   243  		},
   244  	})
   245  }
   246  
   247  func TestAccAWSInstance_disableApiTermination(t *testing.T) {
   248  	var v ec2.Instance
   249  
   250  	checkDisableApiTermination := func(expected bool) resource.TestCheckFunc {
   251  		return func(*terraform.State) error {
   252  			conn := testAccProvider.Meta().(*AWSClient).ec2conn
   253  			r, err := conn.DescribeInstanceAttribute(&ec2.DescribeInstanceAttributeInput{
   254  				InstanceId: v.InstanceId,
   255  				Attribute:  aws.String("disableApiTermination"),
   256  			})
   257  			if err != nil {
   258  				return err
   259  			}
   260  			got := *r.DisableApiTermination.Value
   261  			if got != expected {
   262  				return fmt.Errorf("expected: %t, got: %t", expected, got)
   263  			}
   264  			return nil
   265  		}
   266  	}
   267  
   268  	resource.Test(t, resource.TestCase{
   269  		PreCheck:      func() { testAccPreCheck(t) },
   270  		IDRefreshName: "aws_instance.foo",
   271  		Providers:     testAccProviders,
   272  		CheckDestroy:  testAccCheckInstanceDestroy,
   273  		Steps: []resource.TestStep{
   274  			resource.TestStep{
   275  				Config: testAccInstanceConfigDisableAPITermination(true),
   276  				Check: resource.ComposeTestCheckFunc(
   277  					testAccCheckInstanceExists("aws_instance.foo", &v),
   278  					checkDisableApiTermination(true),
   279  				),
   280  			},
   281  
   282  			resource.TestStep{
   283  				Config: testAccInstanceConfigDisableAPITermination(false),
   284  				Check: resource.ComposeTestCheckFunc(
   285  					testAccCheckInstanceExists("aws_instance.foo", &v),
   286  					checkDisableApiTermination(false),
   287  				),
   288  			},
   289  		},
   290  	})
   291  }
   292  
   293  func TestAccAWSInstance_vpc(t *testing.T) {
   294  	var v ec2.Instance
   295  
   296  	resource.Test(t, resource.TestCase{
   297  		PreCheck:        func() { testAccPreCheck(t) },
   298  		IDRefreshName:   "aws_instance.foo",
   299  		IDRefreshIgnore: []string{"associate_public_ip_address", "user_data"},
   300  		Providers:       testAccProviders,
   301  		CheckDestroy:    testAccCheckInstanceDestroy,
   302  		Steps: []resource.TestStep{
   303  			resource.TestStep{
   304  				Config: testAccInstanceConfigVPC,
   305  				Check: resource.ComposeTestCheckFunc(
   306  					testAccCheckInstanceExists(
   307  						"aws_instance.foo", &v),
   308  					resource.TestCheckResourceAttr(
   309  						"aws_instance.foo",
   310  						"user_data",
   311  						"2fad308761514d9d73c3c7fdc877607e06cf950d"),
   312  				),
   313  			},
   314  		},
   315  	})
   316  }
   317  
   318  func TestAccAWSInstance_multipleRegions(t *testing.T) {
   319  	var v ec2.Instance
   320  
   321  	// record the initialized providers so that we can use them to
   322  	// check for the instances in each region
   323  	var providers []*schema.Provider
   324  	providerFactories := map[string]terraform.ResourceProviderFactory{
   325  		"aws": func() (terraform.ResourceProvider, error) {
   326  			p := Provider()
   327  			providers = append(providers, p.(*schema.Provider))
   328  			return p, nil
   329  		},
   330  	}
   331  
   332  	resource.Test(t, resource.TestCase{
   333  		PreCheck:          func() { testAccPreCheck(t) },
   334  		ProviderFactories: providerFactories,
   335  		CheckDestroy:      testAccCheckInstanceDestroyWithProviders(&providers),
   336  		Steps: []resource.TestStep{
   337  			resource.TestStep{
   338  				Config: testAccInstanceConfigMultipleRegions,
   339  				Check: resource.ComposeTestCheckFunc(
   340  					testAccCheckInstanceExistsWithProviders(
   341  						"aws_instance.foo", &v, &providers),
   342  					testAccCheckInstanceExistsWithProviders(
   343  						"aws_instance.bar", &v, &providers),
   344  				),
   345  			},
   346  		},
   347  	})
   348  }
   349  
   350  func TestAccAWSInstance_NetworkInstanceSecurityGroups(t *testing.T) {
   351  	var v ec2.Instance
   352  
   353  	resource.Test(t, resource.TestCase{
   354  		PreCheck:        func() { testAccPreCheck(t) },
   355  		IDRefreshName:   "aws_instance.foo_instance",
   356  		IDRefreshIgnore: []string{"associate_public_ip_address"},
   357  		Providers:       testAccProviders,
   358  		CheckDestroy:    testAccCheckInstanceDestroy,
   359  		Steps: []resource.TestStep{
   360  			resource.TestStep{
   361  				Config: testAccInstanceNetworkInstanceSecurityGroups,
   362  				Check: resource.ComposeTestCheckFunc(
   363  					testAccCheckInstanceExists(
   364  						"aws_instance.foo_instance", &v),
   365  				),
   366  			},
   367  		},
   368  	})
   369  }
   370  
   371  func TestAccAWSInstance_NetworkInstanceVPCSecurityGroupIDs(t *testing.T) {
   372  	var v ec2.Instance
   373  
   374  	resource.Test(t, resource.TestCase{
   375  		PreCheck:      func() { testAccPreCheck(t) },
   376  		IDRefreshName: "aws_instance.foo_instance",
   377  		Providers:     testAccProviders,
   378  		CheckDestroy:  testAccCheckInstanceDestroy,
   379  		Steps: []resource.TestStep{
   380  			resource.TestStep{
   381  				Config: testAccInstanceNetworkInstanceVPCSecurityGroupIDs,
   382  				Check: resource.ComposeTestCheckFunc(
   383  					testAccCheckInstanceExists(
   384  						"aws_instance.foo_instance", &v),
   385  					resource.TestCheckResourceAttr(
   386  						"aws_instance.foo_instance", "security_groups.#", "0"),
   387  					resource.TestCheckResourceAttr(
   388  						"aws_instance.foo_instance", "vpc_security_group_ids.#", "1"),
   389  				),
   390  			},
   391  		},
   392  	})
   393  }
   394  
   395  func TestAccAWSInstance_tags(t *testing.T) {
   396  	var v ec2.Instance
   397  
   398  	resource.Test(t, resource.TestCase{
   399  		PreCheck:     func() { testAccPreCheck(t) },
   400  		Providers:    testAccProviders,
   401  		CheckDestroy: testAccCheckInstanceDestroy,
   402  		Steps: []resource.TestStep{
   403  			resource.TestStep{
   404  				Config: testAccCheckInstanceConfigTags,
   405  				Check: resource.ComposeTestCheckFunc(
   406  					testAccCheckInstanceExists("aws_instance.foo", &v),
   407  					testAccCheckTags(&v.Tags, "foo", "bar"),
   408  					// Guard against regression of https://github.com/hashicorp/terraform/issues/914
   409  					testAccCheckTags(&v.Tags, "#", ""),
   410  				),
   411  			},
   412  
   413  			resource.TestStep{
   414  				Config: testAccCheckInstanceConfigTagsUpdate,
   415  				Check: resource.ComposeTestCheckFunc(
   416  					testAccCheckInstanceExists("aws_instance.foo", &v),
   417  					testAccCheckTags(&v.Tags, "foo", ""),
   418  					testAccCheckTags(&v.Tags, "bar", "baz"),
   419  				),
   420  			},
   421  		},
   422  	})
   423  }
   424  
   425  func TestAccAWSInstance_privateIP(t *testing.T) {
   426  	var v ec2.Instance
   427  
   428  	testCheckPrivateIP := func() resource.TestCheckFunc {
   429  		return func(*terraform.State) error {
   430  			if *v.PrivateIpAddress != "10.1.1.42" {
   431  				return fmt.Errorf("bad private IP: %s", *v.PrivateIpAddress)
   432  			}
   433  
   434  			return nil
   435  		}
   436  	}
   437  
   438  	resource.Test(t, resource.TestCase{
   439  		PreCheck:      func() { testAccPreCheck(t) },
   440  		IDRefreshName: "aws_instance.foo",
   441  		Providers:     testAccProviders,
   442  		CheckDestroy:  testAccCheckInstanceDestroy,
   443  		Steps: []resource.TestStep{
   444  			resource.TestStep{
   445  				Config: testAccInstanceConfigPrivateIP,
   446  				Check: resource.ComposeTestCheckFunc(
   447  					testAccCheckInstanceExists("aws_instance.foo", &v),
   448  					testCheckPrivateIP(),
   449  				),
   450  			},
   451  		},
   452  	})
   453  }
   454  
   455  func TestAccAWSInstance_associatePublicIPAndPrivateIP(t *testing.T) {
   456  	var v ec2.Instance
   457  
   458  	testCheckPrivateIP := func() resource.TestCheckFunc {
   459  		return func(*terraform.State) error {
   460  			if *v.PrivateIpAddress != "10.1.1.42" {
   461  				return fmt.Errorf("bad private IP: %s", *v.PrivateIpAddress)
   462  			}
   463  
   464  			return nil
   465  		}
   466  	}
   467  
   468  	resource.Test(t, resource.TestCase{
   469  		PreCheck:        func() { testAccPreCheck(t) },
   470  		IDRefreshName:   "aws_instance.foo",
   471  		IDRefreshIgnore: []string{"associate_public_ip_address"},
   472  		Providers:       testAccProviders,
   473  		CheckDestroy:    testAccCheckInstanceDestroy,
   474  		Steps: []resource.TestStep{
   475  			resource.TestStep{
   476  				Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
   477  				Check: resource.ComposeTestCheckFunc(
   478  					testAccCheckInstanceExists("aws_instance.foo", &v),
   479  					testCheckPrivateIP(),
   480  				),
   481  			},
   482  		},
   483  	})
   484  }
   485  
   486  // Guard against regression with KeyPairs
   487  // https://github.com/hashicorp/terraform/issues/2302
   488  func TestAccAWSInstance_keyPairCheck(t *testing.T) {
   489  	var v ec2.Instance
   490  
   491  	testCheckKeyPair := func(keyName string) resource.TestCheckFunc {
   492  		return func(*terraform.State) error {
   493  			if v.KeyName == nil {
   494  				return fmt.Errorf("No Key Pair found, expected(%s)", keyName)
   495  			}
   496  			if v.KeyName != nil && *v.KeyName != keyName {
   497  				return fmt.Errorf("Bad key name, expected (%s), got (%s)", keyName, *v.KeyName)
   498  			}
   499  
   500  			return nil
   501  		}
   502  	}
   503  
   504  	resource.Test(t, resource.TestCase{
   505  		PreCheck:        func() { testAccPreCheck(t) },
   506  		IDRefreshName:   "aws_instance.foo",
   507  		IDRefreshIgnore: []string{"source_dest_check"},
   508  		Providers:       testAccProviders,
   509  		CheckDestroy:    testAccCheckInstanceDestroy,
   510  		Steps: []resource.TestStep{
   511  			resource.TestStep{
   512  				Config: testAccInstanceConfigKeyPair,
   513  				Check: resource.ComposeTestCheckFunc(
   514  					testAccCheckInstanceExists("aws_instance.foo", &v),
   515  					testCheckKeyPair("tmp-key"),
   516  				),
   517  			},
   518  		},
   519  	})
   520  }
   521  
   522  func TestAccAWSInstance_rootBlockDeviceMismatch(t *testing.T) {
   523  	var v ec2.Instance
   524  
   525  	resource.Test(t, resource.TestCase{
   526  		PreCheck:     func() { testAccPreCheck(t) },
   527  		Providers:    testAccProviders,
   528  		CheckDestroy: testAccCheckInstanceDestroy,
   529  		Steps: []resource.TestStep{
   530  			resource.TestStep{
   531  				Config: testAccInstanceConfigRootBlockDeviceMismatch,
   532  				Check: resource.ComposeTestCheckFunc(
   533  					testAccCheckInstanceExists("aws_instance.foo", &v),
   534  					resource.TestCheckResourceAttr(
   535  						"aws_instance.foo", "root_block_device.0.volume_size", "13"),
   536  				),
   537  			},
   538  		},
   539  	})
   540  }
   541  
   542  // This test reproduces the bug here:
   543  //   https://github.com/hashicorp/terraform/issues/1752
   544  //
   545  // I wish there were a way to exercise resources built with helper.Schema in a
   546  // unit context, in which case this test could be moved there, but for now this
   547  // will cover the bugfix.
   548  //
   549  // The following triggers "diffs didn't match during apply" without the fix in to
   550  // set NewRemoved on the .# field when it changes to 0.
   551  func TestAccAWSInstance_forceNewAndTagsDrift(t *testing.T) {
   552  	var v ec2.Instance
   553  
   554  	resource.Test(t, resource.TestCase{
   555  		PreCheck:      func() { testAccPreCheck(t) },
   556  		IDRefreshName: "aws_instance.foo",
   557  		Providers:     testAccProviders,
   558  		CheckDestroy:  testAccCheckInstanceDestroy,
   559  		Steps: []resource.TestStep{
   560  			resource.TestStep{
   561  				Config: testAccInstanceConfigForceNewAndTagsDrift,
   562  				Check: resource.ComposeTestCheckFunc(
   563  					testAccCheckInstanceExists("aws_instance.foo", &v),
   564  					driftTags(&v),
   565  				),
   566  				ExpectNonEmptyPlan: true,
   567  			},
   568  			resource.TestStep{
   569  				Config: testAccInstanceConfigForceNewAndTagsDrift_Update,
   570  				Check: resource.ComposeTestCheckFunc(
   571  					testAccCheckInstanceExists("aws_instance.foo", &v),
   572  				),
   573  			},
   574  		},
   575  	})
   576  }
   577  
   578  func testAccCheckInstanceDestroy(s *terraform.State) error {
   579  	return testAccCheckInstanceDestroyWithProvider(s, testAccProvider)
   580  }
   581  
   582  func testAccCheckInstanceDestroyWithProviders(providers *[]*schema.Provider) resource.TestCheckFunc {
   583  	return func(s *terraform.State) error {
   584  		for _, provider := range *providers {
   585  			if provider.Meta() == nil {
   586  				continue
   587  			}
   588  			if err := testAccCheckInstanceDestroyWithProvider(s, provider); err != nil {
   589  				return err
   590  			}
   591  		}
   592  		return nil
   593  	}
   594  }
   595  
   596  func testAccCheckInstanceDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
   597  	conn := provider.Meta().(*AWSClient).ec2conn
   598  
   599  	for _, rs := range s.RootModule().Resources {
   600  		if rs.Type != "aws_instance" {
   601  			continue
   602  		}
   603  
   604  		// Try to find the resource
   605  		resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{
   606  			InstanceIds: []*string{aws.String(rs.Primary.ID)},
   607  		})
   608  		if err == nil {
   609  			for _, r := range resp.Reservations {
   610  				for _, i := range r.Instances {
   611  					if i.State != nil && *i.State.Name != "terminated" {
   612  						return fmt.Errorf("Found unterminated instance: %s", i)
   613  					}
   614  				}
   615  			}
   616  		}
   617  
   618  		// Verify the error is what we want
   619  		if ae, ok := err.(awserr.Error); ok && ae.Code() == "InvalidInstanceID.NotFound" {
   620  			continue
   621  		}
   622  
   623  		return err
   624  	}
   625  
   626  	return nil
   627  }
   628  
   629  func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFunc {
   630  	providers := []*schema.Provider{testAccProvider}
   631  	return testAccCheckInstanceExistsWithProviders(n, i, &providers)
   632  }
   633  
   634  func testAccCheckInstanceExistsWithProviders(n string, i *ec2.Instance, providers *[]*schema.Provider) resource.TestCheckFunc {
   635  	return func(s *terraform.State) error {
   636  		rs, ok := s.RootModule().Resources[n]
   637  		if !ok {
   638  			return fmt.Errorf("Not found: %s", n)
   639  		}
   640  
   641  		if rs.Primary.ID == "" {
   642  			return fmt.Errorf("No ID is set")
   643  		}
   644  		for _, provider := range *providers {
   645  			// Ignore if Meta is empty, this can happen for validation providers
   646  			if provider.Meta() == nil {
   647  				continue
   648  			}
   649  
   650  			conn := provider.Meta().(*AWSClient).ec2conn
   651  			resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{
   652  				InstanceIds: []*string{aws.String(rs.Primary.ID)},
   653  			})
   654  			if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidInstanceID.NotFound" {
   655  				continue
   656  			}
   657  			if err != nil {
   658  				return err
   659  			}
   660  
   661  			if len(resp.Reservations) > 0 {
   662  				*i = *resp.Reservations[0].Instances[0]
   663  				return nil
   664  			}
   665  		}
   666  
   667  		return fmt.Errorf("Instance not found")
   668  	}
   669  }
   670  
   671  func TestInstanceTenancySchema(t *testing.T) {
   672  	actualSchema := resourceAwsInstance().Schema["tenancy"]
   673  	expectedSchema := &schema.Schema{
   674  		Type:     schema.TypeString,
   675  		Optional: true,
   676  		Computed: true,
   677  		ForceNew: true,
   678  	}
   679  	if !reflect.DeepEqual(actualSchema, expectedSchema) {
   680  		t.Fatalf(
   681  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   682  			actualSchema,
   683  			expectedSchema)
   684  	}
   685  }
   686  
   687  func driftTags(instance *ec2.Instance) resource.TestCheckFunc {
   688  	return func(s *terraform.State) error {
   689  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   690  		_, err := conn.CreateTags(&ec2.CreateTagsInput{
   691  			Resources: []*string{instance.InstanceId},
   692  			Tags: []*ec2.Tag{
   693  				&ec2.Tag{
   694  					Key:   aws.String("Drift"),
   695  					Value: aws.String("Happens"),
   696  				},
   697  			},
   698  		})
   699  		return err
   700  	}
   701  }
   702  
   703  const testAccInstanceConfig_pre = `
   704  resource "aws_security_group" "tf_test_foo" {
   705  	name = "tf_test_foo"
   706  	description = "foo"
   707  
   708  	ingress {
   709  		protocol = "icmp"
   710  		from_port = -1
   711  		to_port = -1
   712  		cidr_blocks = ["0.0.0.0/0"]
   713  	}
   714  }
   715  `
   716  
   717  const testAccInstanceConfig = `
   718  resource "aws_security_group" "tf_test_foo" {
   719  	name = "tf_test_foo"
   720  	description = "foo"
   721  
   722  	ingress {
   723  		protocol = "icmp"
   724  		from_port = -1
   725  		to_port = -1
   726  		cidr_blocks = ["0.0.0.0/0"]
   727  	}
   728  }
   729  
   730  resource "aws_instance" "foo" {
   731  	# us-west-2
   732  	ami = "ami-4fccb37f"
   733  	availability_zone = "us-west-2a"
   734  
   735  	instance_type = "m1.small"
   736  	security_groups = ["${aws_security_group.tf_test_foo.name}"]
   737  	user_data = "foo:-with-character's"
   738  }
   739  `
   740  
   741  const testAccInstanceConfigBlockDevices = `
   742  resource "aws_instance" "foo" {
   743  	# us-west-2
   744  	ami = "ami-55a7ea65"
   745  
   746  	# In order to attach an encrypted volume to an instance you need to have an
   747  	# m3.medium or larger. See "Supported Instance Types" in:
   748  	# http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html
   749  	instance_type = "m3.medium"
   750  
   751  	root_block_device {
   752  		volume_type = "gp2"
   753  		volume_size = 11
   754  	}
   755  	ebs_block_device {
   756  		device_name = "/dev/sdb"
   757  		volume_size = 9
   758  	}
   759  	ebs_block_device {
   760  		device_name = "/dev/sdc"
   761  		volume_size = 10
   762  		volume_type = "io1"
   763  		iops = 100
   764  	}
   765  
   766  	# Encrypted ebs block device
   767  	ebs_block_device {
   768  		device_name = "/dev/sdd"
   769  		volume_size = 12
   770  		encrypted = true
   771  	}
   772  
   773  	ephemeral_block_device {
   774  		device_name = "/dev/sde"
   775  		virtual_name = "ephemeral0"
   776  	}
   777  }
   778  `
   779  
   780  const testAccInstanceConfigSourceDestEnable = `
   781  resource "aws_vpc" "foo" {
   782  	cidr_block = "10.1.0.0/16"
   783  }
   784  
   785  resource "aws_subnet" "foo" {
   786  	cidr_block = "10.1.1.0/24"
   787  	vpc_id = "${aws_vpc.foo.id}"
   788  }
   789  
   790  resource "aws_instance" "foo" {
   791  	# us-west-2
   792  	ami = "ami-4fccb37f"
   793  	instance_type = "m1.small"
   794  	subnet_id = "${aws_subnet.foo.id}"
   795  }
   796  `
   797  
   798  const testAccInstanceConfigSourceDestDisable = `
   799  resource "aws_vpc" "foo" {
   800  	cidr_block = "10.1.0.0/16"
   801  }
   802  
   803  resource "aws_subnet" "foo" {
   804  	cidr_block = "10.1.1.0/24"
   805  	vpc_id = "${aws_vpc.foo.id}"
   806  }
   807  
   808  resource "aws_instance" "foo" {
   809  	# us-west-2
   810  	ami = "ami-4fccb37f"
   811  	instance_type = "m1.small"
   812  	subnet_id = "${aws_subnet.foo.id}"
   813  	source_dest_check = false
   814  }
   815  `
   816  
   817  func testAccInstanceConfigDisableAPITermination(val bool) string {
   818  	return fmt.Sprintf(`
   819  	resource "aws_vpc" "foo" {
   820  		cidr_block = "10.1.0.0/16"
   821  	}
   822  
   823  	resource "aws_subnet" "foo" {
   824  		cidr_block = "10.1.1.0/24"
   825  		vpc_id = "${aws_vpc.foo.id}"
   826  	}
   827  
   828  	resource "aws_instance" "foo" {
   829  		# us-west-2
   830  		ami = "ami-4fccb37f"
   831  		instance_type = "m1.small"
   832  		subnet_id = "${aws_subnet.foo.id}"
   833  		disable_api_termination = %t
   834  	}
   835  	`, val)
   836  }
   837  
   838  const testAccInstanceConfigVPC = `
   839  resource "aws_vpc" "foo" {
   840  	cidr_block = "10.1.0.0/16"
   841  }
   842  
   843  resource "aws_subnet" "foo" {
   844  	cidr_block = "10.1.1.0/24"
   845  	vpc_id = "${aws_vpc.foo.id}"
   846  }
   847  
   848  resource "aws_instance" "foo" {
   849  	# us-west-2
   850  	ami = "ami-4fccb37f"
   851  	instance_type = "m1.small"
   852  	subnet_id = "${aws_subnet.foo.id}"
   853  	associate_public_ip_address = true
   854  	tenancy = "dedicated"
   855  	# pre-encoded base64 data
   856  	user_data = "3dc39dda39be1205215e776bad998da361a5955d"
   857  }
   858  `
   859  
   860  const testAccInstanceConfigMultipleRegions = `
   861  provider "aws" {
   862  	alias = "west"
   863  	region = "us-west-2"
   864  }
   865  
   866  provider "aws" {
   867  	alias = "east"
   868  	region = "us-east-1"
   869  }
   870  
   871  resource "aws_instance" "foo" {
   872  	# us-west-2
   873  	provider = "aws.west"
   874  	ami = "ami-4fccb37f"
   875  	instance_type = "m1.small"
   876  }
   877  
   878  resource "aws_instance" "bar" {
   879  	# us-east-1
   880  	provider = "aws.east"
   881  	ami = "ami-8c6ea9e4"
   882  	instance_type = "m1.small"
   883  }
   884  `
   885  
   886  const testAccCheckInstanceConfigTags = `
   887  resource "aws_instance" "foo" {
   888  	ami = "ami-4fccb37f"
   889  	instance_type = "m1.small"
   890  	tags {
   891  		foo = "bar"
   892  	}
   893  }
   894  `
   895  
   896  const testAccCheckInstanceConfigTagsUpdate = `
   897  resource "aws_instance" "foo" {
   898  	ami = "ami-4fccb37f"
   899  	instance_type = "m1.small"
   900  	tags {
   901  		bar = "baz"
   902  	}
   903  }
   904  `
   905  
   906  const testAccInstanceConfigPrivateIP = `
   907  resource "aws_vpc" "foo" {
   908  	cidr_block = "10.1.0.0/16"
   909  }
   910  
   911  resource "aws_subnet" "foo" {
   912  	cidr_block = "10.1.1.0/24"
   913  	vpc_id = "${aws_vpc.foo.id}"
   914  }
   915  
   916  resource "aws_instance" "foo" {
   917  	ami = "ami-c5eabbf5"
   918  	instance_type = "t2.micro"
   919  	subnet_id = "${aws_subnet.foo.id}"
   920  	private_ip = "10.1.1.42"
   921  }
   922  `
   923  
   924  const testAccInstanceConfigAssociatePublicIPAndPrivateIP = `
   925  resource "aws_vpc" "foo" {
   926  	cidr_block = "10.1.0.0/16"
   927  }
   928  
   929  resource "aws_subnet" "foo" {
   930  	cidr_block = "10.1.1.0/24"
   931  	vpc_id = "${aws_vpc.foo.id}"
   932  }
   933  
   934  resource "aws_instance" "foo" {
   935  	ami = "ami-c5eabbf5"
   936  	instance_type = "t2.micro"
   937  	subnet_id = "${aws_subnet.foo.id}"
   938  	associate_public_ip_address = true
   939  	private_ip = "10.1.1.42"
   940  }
   941  `
   942  
   943  const testAccInstanceNetworkInstanceSecurityGroups = `
   944  resource "aws_internet_gateway" "gw" {
   945    vpc_id = "${aws_vpc.foo.id}"
   946  }
   947  
   948  resource "aws_vpc" "foo" {
   949    cidr_block = "10.1.0.0/16"
   950  	tags {
   951  		Name = "tf-network-test"
   952  	}
   953  }
   954  
   955  resource "aws_security_group" "tf_test_foo" {
   956    name = "tf_test_foo"
   957    description = "foo"
   958    vpc_id="${aws_vpc.foo.id}"
   959  
   960    ingress {
   961      protocol = "icmp"
   962      from_port = -1
   963      to_port = -1
   964      cidr_blocks = ["0.0.0.0/0"]
   965    }
   966  }
   967  
   968  resource "aws_subnet" "foo" {
   969    cidr_block = "10.1.1.0/24"
   970    vpc_id = "${aws_vpc.foo.id}"
   971  }
   972  
   973  resource "aws_instance" "foo_instance" {
   974    ami = "ami-21f78e11"
   975    instance_type = "t1.micro"
   976    vpc_security_group_ids = ["${aws_security_group.tf_test_foo.id}"]
   977    subnet_id = "${aws_subnet.foo.id}"
   978    associate_public_ip_address = true
   979  	depends_on = ["aws_internet_gateway.gw"]
   980  }
   981  
   982  resource "aws_eip" "foo_eip" {
   983    instance = "${aws_instance.foo_instance.id}"
   984    vpc = true
   985  	depends_on = ["aws_internet_gateway.gw"]
   986  }
   987  `
   988  
   989  const testAccInstanceNetworkInstanceVPCSecurityGroupIDs = `
   990  resource "aws_internet_gateway" "gw" {
   991    vpc_id = "${aws_vpc.foo.id}"
   992  }
   993  
   994  resource "aws_vpc" "foo" {
   995    cidr_block = "10.1.0.0/16"
   996  	tags {
   997  		Name = "tf-network-test"
   998  	}
   999  }
  1000  
  1001  resource "aws_security_group" "tf_test_foo" {
  1002    name = "tf_test_foo"
  1003    description = "foo"
  1004    vpc_id="${aws_vpc.foo.id}"
  1005  
  1006    ingress {
  1007      protocol = "icmp"
  1008      from_port = -1
  1009      to_port = -1
  1010      cidr_blocks = ["0.0.0.0/0"]
  1011    }
  1012  }
  1013  
  1014  resource "aws_subnet" "foo" {
  1015    cidr_block = "10.1.1.0/24"
  1016    vpc_id = "${aws_vpc.foo.id}"
  1017  }
  1018  
  1019  resource "aws_instance" "foo_instance" {
  1020    ami = "ami-21f78e11"
  1021    instance_type = "t1.micro"
  1022    vpc_security_group_ids = ["${aws_security_group.tf_test_foo.id}"]
  1023    subnet_id = "${aws_subnet.foo.id}"
  1024  	depends_on = ["aws_internet_gateway.gw"]
  1025  }
  1026  
  1027  resource "aws_eip" "foo_eip" {
  1028    instance = "${aws_instance.foo_instance.id}"
  1029    vpc = true
  1030  	depends_on = ["aws_internet_gateway.gw"]
  1031  }
  1032  `
  1033  
  1034  const testAccInstanceConfigKeyPair = `
  1035  provider "aws" {
  1036  	region = "us-east-1"
  1037  }
  1038  
  1039  resource "aws_key_pair" "debugging" {
  1040  	key_name = "tmp-key"
  1041  	public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 phodgson@thoughtworks.com"
  1042  }
  1043  
  1044  resource "aws_instance" "foo" {
  1045    ami = "ami-408c7f28"
  1046    instance_type = "t1.micro"
  1047    key_name = "${aws_key_pair.debugging.key_name}"
  1048  	tags {
  1049  		Name = "testAccInstanceConfigKeyPair_TestAMI"
  1050  	}
  1051  }
  1052  `
  1053  
  1054  const testAccInstanceConfigRootBlockDeviceMismatch = `
  1055  resource "aws_vpc" "foo" {
  1056  	cidr_block = "10.1.0.0/16"
  1057  }
  1058  
  1059  resource "aws_subnet" "foo" {
  1060  	cidr_block = "10.1.1.0/24"
  1061  	vpc_id = "${aws_vpc.foo.id}"
  1062  }
  1063  
  1064  resource "aws_instance" "foo" {
  1065  	// This is an AMI with RootDeviceName: "/dev/sda1"; actual root: "/dev/sda"
  1066  	ami = "ami-ef5b69df"
  1067  	instance_type = "t1.micro"
  1068  	subnet_id = "${aws_subnet.foo.id}"
  1069  	root_block_device {
  1070  		volume_size = 13
  1071  	}
  1072  }
  1073  `
  1074  
  1075  const testAccInstanceConfigForceNewAndTagsDrift = `
  1076  resource "aws_vpc" "foo" {
  1077  	cidr_block = "10.1.0.0/16"
  1078  }
  1079  
  1080  resource "aws_subnet" "foo" {
  1081  	cidr_block = "10.1.1.0/24"
  1082  	vpc_id = "${aws_vpc.foo.id}"
  1083  }
  1084  
  1085  resource "aws_instance" "foo" {
  1086  	ami = "ami-22b9a343"
  1087  	instance_type = "t2.nano"
  1088  	subnet_id = "${aws_subnet.foo.id}"
  1089  }
  1090  `
  1091  
  1092  const testAccInstanceConfigForceNewAndTagsDrift_Update = `
  1093  resource "aws_vpc" "foo" {
  1094  	cidr_block = "10.1.0.0/16"
  1095  }
  1096  
  1097  resource "aws_subnet" "foo" {
  1098  	cidr_block = "10.1.1.0/24"
  1099  	vpc_id = "${aws_vpc.foo.id}"
  1100  }
  1101  
  1102  resource "aws_instance" "foo" {
  1103  	ami = "ami-22b9a343"
  1104  	instance_type = "t2.micro"
  1105  	subnet_id = "${aws_subnet.foo.id}"
  1106  }
  1107  `