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