github.com/tarrant/terraform@v0.3.8-0.20150402012457-f68c9eee638e/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/hashicorp/aws-sdk-go/aws" 9 "github.com/hashicorp/aws-sdk-go/gen/ec2" 10 "github.com/hashicorp/terraform/helper/resource" 11 "github.com/hashicorp/terraform/helper/schema" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func TestAccAWSInstance_normal(t *testing.T) { 16 var v ec2.Instance 17 var vol *ec2.Volume 18 19 testCheck := func(*terraform.State) error { 20 if *v.Placement.AvailabilityZone != "us-west-2a" { 21 return fmt.Errorf("bad availability zone: %#v", *v.Placement.AvailabilityZone) 22 } 23 24 if len(v.SecurityGroups) == 0 { 25 return fmt.Errorf("no security groups: %#v", v.SecurityGroups) 26 } 27 if *v.SecurityGroups[0].GroupName != "tf_test_foo" { 28 return fmt.Errorf("no security groups: %#v", v.SecurityGroups) 29 } 30 31 return nil 32 } 33 34 resource.Test(t, resource.TestCase{ 35 PreCheck: func() { testAccPreCheck(t) }, 36 Providers: testAccProviders, 37 CheckDestroy: testAccCheckInstanceDestroy, 38 Steps: []resource.TestStep{ 39 // Create a volume to cover #1249 40 resource.TestStep{ 41 // Need a resource in this config so the provisioner will be available 42 Config: testAccInstanceConfig_pre, 43 Check: func(*terraform.State) error { 44 conn := testAccProvider.Meta().(*AWSClient).ec2conn 45 var err error 46 vol, err = conn.CreateVolume(&ec2.CreateVolumeRequest{ 47 AvailabilityZone: aws.String("us-west-2a"), 48 Size: aws.Integer(5), 49 }) 50 return err 51 }, 52 }, 53 54 resource.TestStep{ 55 Config: testAccInstanceConfig, 56 Check: resource.ComposeTestCheckFunc( 57 testAccCheckInstanceExists( 58 "aws_instance.foo", &v), 59 testCheck, 60 resource.TestCheckResourceAttr( 61 "aws_instance.foo", 62 "user_data", 63 "3dc39dda39be1205215e776bad998da361a5955d"), 64 resource.TestCheckResourceAttr( 65 "aws_instance.foo", "ebs_block_device.#", "0"), 66 ), 67 }, 68 69 // We repeat the exact same test so that we can be sure 70 // that the user data hash stuff is working without generating 71 // an incorrect diff. 72 resource.TestStep{ 73 Config: testAccInstanceConfig, 74 Check: resource.ComposeTestCheckFunc( 75 testAccCheckInstanceExists( 76 "aws_instance.foo", &v), 77 testCheck, 78 resource.TestCheckResourceAttr( 79 "aws_instance.foo", 80 "user_data", 81 "3dc39dda39be1205215e776bad998da361a5955d"), 82 resource.TestCheckResourceAttr( 83 "aws_instance.foo", "ebs_block_device.#", "0"), 84 ), 85 }, 86 87 // Clean up volume created above 88 resource.TestStep{ 89 Config: testAccInstanceConfig, 90 Check: func(*terraform.State) error { 91 conn := testAccProvider.Meta().(*AWSClient).ec2conn 92 return conn.DeleteVolume(&ec2.DeleteVolumeRequest{VolumeID: vol.VolumeID}) 93 }, 94 }, 95 }, 96 }) 97 } 98 99 func TestAccAWSInstance_blockDevices(t *testing.T) { 100 var v ec2.Instance 101 102 testCheck := func() resource.TestCheckFunc { 103 return func(*terraform.State) error { 104 105 // Map out the block devices by name, which should be unique. 106 blockDevices := make(map[string]ec2.InstanceBlockDeviceMapping) 107 for _, blockDevice := range v.BlockDeviceMappings { 108 blockDevices[*blockDevice.DeviceName] = blockDevice 109 } 110 111 // Check if the root block device exists. 112 if _, ok := blockDevices["/dev/sda1"]; !ok { 113 fmt.Errorf("block device doesn't exist: /dev/sda1") 114 } 115 116 // Check if the secondary block device exists. 117 if _, ok := blockDevices["/dev/sdb"]; !ok { 118 fmt.Errorf("block device doesn't exist: /dev/sdb") 119 } 120 121 // Check if the third block device exists. 122 if _, ok := blockDevices["/dev/sdc"]; !ok { 123 fmt.Errorf("block device doesn't exist: /dev/sdc") 124 } 125 126 return nil 127 } 128 } 129 130 resource.Test(t, resource.TestCase{ 131 PreCheck: func() { testAccPreCheck(t) }, 132 Providers: testAccProviders, 133 CheckDestroy: testAccCheckInstanceDestroy, 134 Steps: []resource.TestStep{ 135 resource.TestStep{ 136 Config: testAccInstanceConfigBlockDevices, 137 Check: resource.ComposeTestCheckFunc( 138 testAccCheckInstanceExists( 139 "aws_instance.foo", &v), 140 resource.TestCheckResourceAttr( 141 "aws_instance.foo", "root_block_device.#", "1"), 142 resource.TestCheckResourceAttr( 143 "aws_instance.foo", "root_block_device.1023169747.volume_size", "11"), 144 resource.TestCheckResourceAttr( 145 "aws_instance.foo", "root_block_device.1023169747.volume_type", "gp2"), 146 resource.TestCheckResourceAttr( 147 "aws_instance.foo", "ebs_block_device.#", "2"), 148 resource.TestCheckResourceAttr( 149 "aws_instance.foo", "ebs_block_device.2225977507.device_name", "/dev/sdb"), 150 resource.TestCheckResourceAttr( 151 "aws_instance.foo", "ebs_block_device.2225977507.volume_size", "9"), 152 resource.TestCheckResourceAttr( 153 "aws_instance.foo", "ebs_block_device.2225977507.volume_type", "standard"), 154 resource.TestCheckResourceAttr( 155 "aws_instance.foo", "ebs_block_device.1977224956.device_name", "/dev/sdc"), 156 resource.TestCheckResourceAttr( 157 "aws_instance.foo", "ebs_block_device.1977224956.volume_size", "10"), 158 resource.TestCheckResourceAttr( 159 "aws_instance.foo", "ebs_block_device.1977224956.volume_type", "io1"), 160 resource.TestCheckResourceAttr( 161 "aws_instance.foo", "ebs_block_device.1977224956.iops", "100"), 162 resource.TestCheckResourceAttr( 163 "aws_instance.foo", "ephemeral_block_device.#", "1"), 164 resource.TestCheckResourceAttr( 165 "aws_instance.foo", "ephemeral_block_device.1692014856.device_name", "/dev/sde"), 166 resource.TestCheckResourceAttr( 167 "aws_instance.foo", "ephemeral_block_device.1692014856.virtual_name", "ephemeral0"), 168 testCheck(), 169 ), 170 }, 171 }, 172 }) 173 } 174 175 func TestAccAWSInstance_sourceDestCheck(t *testing.T) { 176 var v ec2.Instance 177 178 testCheck := func(enabled bool) resource.TestCheckFunc { 179 return func(*terraform.State) error { 180 if *v.SourceDestCheck != enabled { 181 return fmt.Errorf("bad source_dest_check: %#v", *v.SourceDestCheck) 182 } 183 184 return nil 185 } 186 } 187 188 resource.Test(t, resource.TestCase{ 189 PreCheck: func() { testAccPreCheck(t) }, 190 Providers: testAccProviders, 191 CheckDestroy: testAccCheckInstanceDestroy, 192 Steps: []resource.TestStep{ 193 resource.TestStep{ 194 Config: testAccInstanceConfigSourceDestDisable, 195 Check: resource.ComposeTestCheckFunc( 196 testAccCheckInstanceExists("aws_instance.foo", &v), 197 testCheck(false), 198 ), 199 }, 200 201 resource.TestStep{ 202 Config: testAccInstanceConfigSourceDestEnable, 203 Check: resource.ComposeTestCheckFunc( 204 testAccCheckInstanceExists("aws_instance.foo", &v), 205 testCheck(true), 206 ), 207 }, 208 209 resource.TestStep{ 210 Config: testAccInstanceConfigSourceDestDisable, 211 Check: resource.ComposeTestCheckFunc( 212 testAccCheckInstanceExists("aws_instance.foo", &v), 213 testCheck(false), 214 ), 215 }, 216 }, 217 }) 218 } 219 220 func TestAccAWSInstance_vpc(t *testing.T) { 221 var v ec2.Instance 222 223 resource.Test(t, resource.TestCase{ 224 PreCheck: func() { testAccPreCheck(t) }, 225 Providers: testAccProviders, 226 CheckDestroy: testAccCheckInstanceDestroy, 227 Steps: []resource.TestStep{ 228 resource.TestStep{ 229 Config: testAccInstanceConfigVPC, 230 Check: resource.ComposeTestCheckFunc( 231 testAccCheckInstanceExists( 232 "aws_instance.foo", &v), 233 ), 234 }, 235 }, 236 }) 237 } 238 239 func TestAccInstance_NetworkInstanceSecurityGroups(t *testing.T) { 240 var v ec2.Instance 241 242 resource.Test(t, resource.TestCase{ 243 PreCheck: func() { testAccPreCheck(t) }, 244 Providers: testAccProviders, 245 CheckDestroy: testAccCheckInstanceDestroy, 246 Steps: []resource.TestStep{ 247 resource.TestStep{ 248 Config: testAccInstanceNetworkInstanceSecurityGroups, 249 Check: resource.ComposeTestCheckFunc( 250 testAccCheckInstanceExists( 251 "aws_instance.foo_instance", &v), 252 ), 253 }, 254 }, 255 }) 256 } 257 258 func TestAccAWSInstance_tags(t *testing.T) { 259 var v ec2.Instance 260 261 resource.Test(t, resource.TestCase{ 262 PreCheck: func() { testAccPreCheck(t) }, 263 Providers: testAccProviders, 264 CheckDestroy: testAccCheckInstanceDestroy, 265 Steps: []resource.TestStep{ 266 resource.TestStep{ 267 Config: testAccCheckInstanceConfigTags, 268 Check: resource.ComposeTestCheckFunc( 269 testAccCheckInstanceExists("aws_instance.foo", &v), 270 testAccCheckTags(&v.Tags, "foo", "bar"), 271 // Guard against regression of https://github.com/hashicorp/terraform/issues/914 272 testAccCheckTags(&v.Tags, "#", ""), 273 ), 274 }, 275 276 resource.TestStep{ 277 Config: testAccCheckInstanceConfigTagsUpdate, 278 Check: resource.ComposeTestCheckFunc( 279 testAccCheckInstanceExists("aws_instance.foo", &v), 280 testAccCheckTags(&v.Tags, "foo", ""), 281 testAccCheckTags(&v.Tags, "bar", "baz"), 282 ), 283 }, 284 }, 285 }) 286 } 287 288 func TestAccAWSInstance_privateIP(t *testing.T) { 289 var v ec2.Instance 290 291 testCheckPrivateIP := func() resource.TestCheckFunc { 292 return func(*terraform.State) error { 293 if *v.PrivateIPAddress != "10.1.1.42" { 294 return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress) 295 } 296 297 return nil 298 } 299 } 300 301 resource.Test(t, resource.TestCase{ 302 PreCheck: func() { testAccPreCheck(t) }, 303 Providers: testAccProviders, 304 CheckDestroy: testAccCheckInstanceDestroy, 305 Steps: []resource.TestStep{ 306 resource.TestStep{ 307 Config: testAccInstanceConfigPrivateIP, 308 Check: resource.ComposeTestCheckFunc( 309 testAccCheckInstanceExists("aws_instance.foo", &v), 310 testCheckPrivateIP(), 311 ), 312 }, 313 }, 314 }) 315 } 316 317 func TestAccAWSInstance_associatePublicIPAndPrivateIP(t *testing.T) { 318 var v ec2.Instance 319 320 testCheckPrivateIP := func() resource.TestCheckFunc { 321 return func(*terraform.State) error { 322 if *v.PrivateIPAddress != "10.1.1.42" { 323 return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress) 324 } 325 326 return nil 327 } 328 } 329 330 resource.Test(t, resource.TestCase{ 331 PreCheck: func() { testAccPreCheck(t) }, 332 Providers: testAccProviders, 333 CheckDestroy: testAccCheckInstanceDestroy, 334 Steps: []resource.TestStep{ 335 resource.TestStep{ 336 Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP, 337 Check: resource.ComposeTestCheckFunc( 338 testAccCheckInstanceExists("aws_instance.foo", &v), 339 testCheckPrivateIP(), 340 ), 341 }, 342 }, 343 }) 344 } 345 346 func testAccCheckInstanceDestroy(s *terraform.State) error { 347 conn := testAccProvider.Meta().(*AWSClient).ec2conn 348 349 for _, rs := range s.RootModule().Resources { 350 if rs.Type != "aws_instance" { 351 continue 352 } 353 354 // Try to find the resource 355 resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{ 356 InstanceIDs: []string{rs.Primary.ID}, 357 }) 358 if err == nil { 359 if len(resp.Reservations) > 0 { 360 return fmt.Errorf("still exist.") 361 } 362 363 return nil 364 } 365 366 // Verify the error is what we want 367 ec2err, ok := err.(aws.APIError) 368 if !ok { 369 return err 370 } 371 if ec2err.Code != "InvalidInstanceID.NotFound" { 372 return err 373 } 374 } 375 376 return nil 377 } 378 379 func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFunc { 380 return func(s *terraform.State) error { 381 rs, ok := s.RootModule().Resources[n] 382 if !ok { 383 return fmt.Errorf("Not found: %s", n) 384 } 385 386 if rs.Primary.ID == "" { 387 return fmt.Errorf("No ID is set") 388 } 389 390 conn := testAccProvider.Meta().(*AWSClient).ec2conn 391 resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{ 392 InstanceIDs: []string{rs.Primary.ID}, 393 }) 394 if err != nil { 395 return err 396 } 397 if len(resp.Reservations) == 0 { 398 return fmt.Errorf("Instance not found") 399 } 400 401 *i = resp.Reservations[0].Instances[0] 402 403 return nil 404 } 405 } 406 407 func TestInstanceTenancySchema(t *testing.T) { 408 actualSchema := resourceAwsInstance().Schema["tenancy"] 409 expectedSchema := &schema.Schema{ 410 Type: schema.TypeString, 411 Optional: true, 412 Computed: true, 413 ForceNew: true, 414 } 415 if !reflect.DeepEqual(actualSchema, expectedSchema) { 416 t.Fatalf( 417 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 418 actualSchema, 419 expectedSchema) 420 } 421 } 422 423 const testAccInstanceConfig_pre = ` 424 resource "aws_security_group" "tf_test_foo" { 425 name = "tf_test_foo" 426 description = "foo" 427 428 ingress { 429 protocol = "icmp" 430 from_port = -1 431 to_port = -1 432 cidr_blocks = ["0.0.0.0/0"] 433 } 434 } 435 ` 436 437 const testAccInstanceConfig = ` 438 resource "aws_security_group" "tf_test_foo" { 439 name = "tf_test_foo" 440 description = "foo" 441 442 ingress { 443 protocol = "icmp" 444 from_port = -1 445 to_port = -1 446 cidr_blocks = ["0.0.0.0/0"] 447 } 448 } 449 450 resource "aws_instance" "foo" { 451 # us-west-2 452 ami = "ami-4fccb37f" 453 availability_zone = "us-west-2a" 454 455 instance_type = "m1.small" 456 security_groups = ["${aws_security_group.tf_test_foo.name}"] 457 user_data = "foo:-with-character's" 458 } 459 ` 460 461 const testAccInstanceConfigBlockDevices = ` 462 resource "aws_instance" "foo" { 463 # us-west-2 464 ami = "ami-55a7ea65" 465 instance_type = "m1.small" 466 467 root_block_device { 468 volume_type = "gp2" 469 volume_size = 11 470 } 471 ebs_block_device { 472 device_name = "/dev/sdb" 473 volume_size = 9 474 } 475 ebs_block_device { 476 device_name = "/dev/sdc" 477 volume_size = 10 478 volume_type = "io1" 479 iops = 100 480 } 481 ephemeral_block_device { 482 device_name = "/dev/sde" 483 virtual_name = "ephemeral0" 484 } 485 } 486 ` 487 488 const testAccInstanceConfigSourceDestEnable = ` 489 resource "aws_vpc" "foo" { 490 cidr_block = "10.1.0.0/16" 491 } 492 493 resource "aws_subnet" "foo" { 494 cidr_block = "10.1.1.0/24" 495 vpc_id = "${aws_vpc.foo.id}" 496 } 497 498 resource "aws_instance" "foo" { 499 # us-west-2 500 ami = "ami-4fccb37f" 501 instance_type = "m1.small" 502 subnet_id = "${aws_subnet.foo.id}" 503 source_dest_check = true 504 } 505 ` 506 507 const testAccInstanceConfigSourceDestDisable = ` 508 resource "aws_vpc" "foo" { 509 cidr_block = "10.1.0.0/16" 510 } 511 512 resource "aws_subnet" "foo" { 513 cidr_block = "10.1.1.0/24" 514 vpc_id = "${aws_vpc.foo.id}" 515 } 516 517 resource "aws_instance" "foo" { 518 # us-west-2 519 ami = "ami-4fccb37f" 520 instance_type = "m1.small" 521 subnet_id = "${aws_subnet.foo.id}" 522 source_dest_check = false 523 } 524 ` 525 526 const testAccInstanceConfigVPC = ` 527 resource "aws_vpc" "foo" { 528 cidr_block = "10.1.0.0/16" 529 } 530 531 resource "aws_subnet" "foo" { 532 cidr_block = "10.1.1.0/24" 533 vpc_id = "${aws_vpc.foo.id}" 534 } 535 536 resource "aws_instance" "foo" { 537 # us-west-2 538 ami = "ami-4fccb37f" 539 instance_type = "m1.small" 540 subnet_id = "${aws_subnet.foo.id}" 541 associate_public_ip_address = true 542 tenancy = "dedicated" 543 } 544 ` 545 546 const testAccCheckInstanceConfigTags = ` 547 resource "aws_instance" "foo" { 548 ami = "ami-4fccb37f" 549 instance_type = "m1.small" 550 tags { 551 foo = "bar" 552 } 553 } 554 ` 555 556 const testAccCheckInstanceConfigTagsUpdate = ` 557 resource "aws_instance" "foo" { 558 ami = "ami-4fccb37f" 559 instance_type = "m1.small" 560 tags { 561 bar = "baz" 562 } 563 } 564 ` 565 566 const testAccInstanceConfigPrivateIP = ` 567 resource "aws_vpc" "foo" { 568 cidr_block = "10.1.0.0/16" 569 } 570 571 resource "aws_subnet" "foo" { 572 cidr_block = "10.1.1.0/24" 573 vpc_id = "${aws_vpc.foo.id}" 574 } 575 576 resource "aws_instance" "foo" { 577 ami = "ami-c5eabbf5" 578 instance_type = "t2.micro" 579 subnet_id = "${aws_subnet.foo.id}" 580 private_ip = "10.1.1.42" 581 } 582 ` 583 584 const testAccInstanceConfigAssociatePublicIPAndPrivateIP = ` 585 resource "aws_vpc" "foo" { 586 cidr_block = "10.1.0.0/16" 587 } 588 589 resource "aws_subnet" "foo" { 590 cidr_block = "10.1.1.0/24" 591 vpc_id = "${aws_vpc.foo.id}" 592 } 593 594 resource "aws_instance" "foo" { 595 ami = "ami-c5eabbf5" 596 instance_type = "t2.micro" 597 subnet_id = "${aws_subnet.foo.id}" 598 associate_public_ip_address = true 599 private_ip = "10.1.1.42" 600 } 601 ` 602 603 const testAccInstanceNetworkInstanceSecurityGroups = ` 604 resource "aws_internet_gateway" "gw" { 605 vpc_id = "${aws_vpc.foo.id}" 606 } 607 608 resource "aws_vpc" "foo" { 609 cidr_block = "10.1.0.0/16" 610 tags { 611 Name = "tf-network-test" 612 } 613 } 614 615 resource "aws_security_group" "tf_test_foo" { 616 name = "tf_test_foo" 617 description = "foo" 618 vpc_id="${aws_vpc.foo.id}" 619 620 ingress { 621 protocol = "icmp" 622 from_port = -1 623 to_port = -1 624 cidr_blocks = ["0.0.0.0/0"] 625 } 626 } 627 628 resource "aws_subnet" "foo" { 629 cidr_block = "10.1.1.0/24" 630 vpc_id = "${aws_vpc.foo.id}" 631 } 632 633 resource "aws_instance" "foo_instance" { 634 ami = "ami-21f78e11" 635 instance_type = "t1.micro" 636 security_groups = ["${aws_security_group.tf_test_foo.id}"] 637 subnet_id = "${aws_subnet.foo.id}" 638 associate_public_ip_address = true 639 depends_on = ["aws_internet_gateway.gw"] 640 } 641 642 resource "aws_eip" "foo_eip" { 643 instance = "${aws_instance.foo_instance.id}" 644 vpc = true 645 depends_on = ["aws_internet_gateway.gw"] 646 } 647 `