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