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