github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/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{"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", "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"}, 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 "562a3e32810edf6ff09994f050f12e799452379d"), 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 `