github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/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/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 "github.com/hashicorp/terraform/terraform" 11 "github.com/mitchellh/goamz/ec2" 12 ) 13 14 func TestAccAWSInstance_normal(t *testing.T) { 15 var v ec2.Instance 16 17 testCheck := func(*terraform.State) error { 18 if v.AvailZone != "us-west-2a" { 19 return fmt.Errorf("bad availability zone: %#v", v.AvailZone) 20 } 21 22 if len(v.SecurityGroups) == 0 { 23 return fmt.Errorf("no security groups: %#v", v.SecurityGroups) 24 } 25 if v.SecurityGroups[0].Name != "tf_test_foo" { 26 return fmt.Errorf("no security groups: %#v", v.SecurityGroups) 27 } 28 29 return nil 30 } 31 32 resource.Test(t, resource.TestCase{ 33 PreCheck: func() { testAccPreCheck(t) }, 34 Providers: testAccProviders, 35 CheckDestroy: testAccCheckInstanceDestroy, 36 Steps: []resource.TestStep{ 37 resource.TestStep{ 38 Config: testAccInstanceConfig, 39 Check: resource.ComposeTestCheckFunc( 40 testAccCheckInstanceExists( 41 "aws_instance.foo", &v), 42 testCheck, 43 resource.TestCheckResourceAttr( 44 "aws_instance.foo", 45 "user_data", 46 "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), 47 ), 48 }, 49 50 // We repeat the exact same test so that we can be sure 51 // that the user data hash stuff is working without generating 52 // an incorrect diff. 53 resource.TestStep{ 54 Config: testAccInstanceConfig, 55 Check: resource.ComposeTestCheckFunc( 56 testAccCheckInstanceExists( 57 "aws_instance.foo", &v), 58 testCheck, 59 resource.TestCheckResourceAttr( 60 "aws_instance.foo", 61 "user_data", 62 "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), 63 ), 64 }, 65 }, 66 }) 67 } 68 69 func TestAccAWSInstance_blockDevices(t *testing.T) { 70 var v ec2.Instance 71 72 testCheck := func() resource.TestCheckFunc { 73 return func(*terraform.State) error { 74 75 // Map out the block devices by name, which should be unique. 76 blockDevices := make(map[string]ec2.BlockDevice) 77 for _, blockDevice := range v.BlockDevices { 78 blockDevices[blockDevice.DeviceName] = blockDevice 79 } 80 81 // Check if the root block device exists. 82 if _, ok := blockDevices["/dev/sda1"]; !ok { 83 fmt.Errorf("block device doesn't exist: /dev/sda1") 84 } 85 86 // Check if the secondary block device exists. 87 if _, ok := blockDevices["/dev/sdb"]; !ok { 88 fmt.Errorf("block device doesn't exist: /dev/sdb") 89 } 90 91 return nil 92 } 93 } 94 95 resource.Test(t, resource.TestCase{ 96 PreCheck: func() { testAccPreCheck(t) }, 97 Providers: testAccProviders, 98 CheckDestroy: testAccCheckInstanceDestroy, 99 Steps: []resource.TestStep{ 100 resource.TestStep{ 101 Config: testAccInstanceConfigBlockDevices, 102 Check: resource.ComposeTestCheckFunc( 103 testAccCheckInstanceExists( 104 "aws_instance.foo", &v), 105 resource.TestCheckResourceAttr( 106 "aws_instance.foo", "root_block_device.#", "1"), 107 resource.TestCheckResourceAttr( 108 "aws_instance.foo", "root_block_device.0.device_name", "/dev/sda1"), 109 resource.TestCheckResourceAttr( 110 "aws_instance.foo", "root_block_device.0.volume_size", "11"), 111 // this one is important because it's the only root_block_device 112 // attribute that comes back from the API. so checking it verifies 113 // that we set state properly 114 resource.TestCheckResourceAttr( 115 "aws_instance.foo", "root_block_device.0.volume_type", "gp2"), 116 resource.TestCheckResourceAttr( 117 "aws_instance.foo", "block_device.#", "1"), 118 resource.TestCheckResourceAttr( 119 "aws_instance.foo", "block_device.172787947.device_name", "/dev/sdb"), 120 resource.TestCheckResourceAttr( 121 "aws_instance.foo", "block_device.172787947.volume_size", "9"), 122 testCheck(), 123 ), 124 }, 125 }, 126 }) 127 } 128 129 func TestAccAWSInstance_sourceDestCheck(t *testing.T) { 130 var v ec2.Instance 131 132 testCheck := func(enabled bool) resource.TestCheckFunc { 133 return func(*terraform.State) error { 134 if v.SourceDestCheck != enabled { 135 return fmt.Errorf("bad source_dest_check: %#v", v.SourceDestCheck) 136 } 137 138 return nil 139 } 140 } 141 142 resource.Test(t, resource.TestCase{ 143 PreCheck: func() { testAccPreCheck(t) }, 144 Providers: testAccProviders, 145 CheckDestroy: testAccCheckInstanceDestroy, 146 Steps: []resource.TestStep{ 147 resource.TestStep{ 148 Config: testAccInstanceConfigSourceDestDisable, 149 Check: resource.ComposeTestCheckFunc( 150 testAccCheckInstanceExists("aws_instance.foo", &v), 151 testCheck(false), 152 ), 153 }, 154 155 resource.TestStep{ 156 Config: testAccInstanceConfigSourceDestEnable, 157 Check: resource.ComposeTestCheckFunc( 158 testAccCheckInstanceExists("aws_instance.foo", &v), 159 testCheck(true), 160 ), 161 }, 162 163 resource.TestStep{ 164 Config: testAccInstanceConfigSourceDestDisable, 165 Check: resource.ComposeTestCheckFunc( 166 testAccCheckInstanceExists("aws_instance.foo", &v), 167 testCheck(false), 168 ), 169 }, 170 }, 171 }) 172 } 173 174 func TestAccAWSInstance_vpc(t *testing.T) { 175 var v ec2.Instance 176 177 resource.Test(t, resource.TestCase{ 178 PreCheck: func() { testAccPreCheck(t) }, 179 Providers: testAccProviders, 180 CheckDestroy: testAccCheckInstanceDestroy, 181 Steps: []resource.TestStep{ 182 resource.TestStep{ 183 Config: testAccInstanceConfigVPC, 184 Check: resource.ComposeTestCheckFunc( 185 testAccCheckInstanceExists( 186 "aws_instance.foo", &v), 187 ), 188 }, 189 }, 190 }) 191 } 192 193 func TestAccInstance_tags(t *testing.T) { 194 var v ec2.Instance 195 196 resource.Test(t, resource.TestCase{ 197 PreCheck: func() { testAccPreCheck(t) }, 198 Providers: testAccProviders, 199 CheckDestroy: testAccCheckInstanceDestroy, 200 Steps: []resource.TestStep{ 201 resource.TestStep{ 202 Config: testAccCheckInstanceConfigTags, 203 Check: resource.ComposeTestCheckFunc( 204 testAccCheckInstanceExists("aws_instance.foo", &v), 205 testAccCheckTags(&v.Tags, "foo", "bar"), 206 // Guard against regression of https://github.com/hashicorp/terraform/issues/914 207 testAccCheckTags(&v.Tags, "#", ""), 208 ), 209 }, 210 211 resource.TestStep{ 212 Config: testAccCheckInstanceConfigTagsUpdate, 213 Check: resource.ComposeTestCheckFunc( 214 testAccCheckInstanceExists("aws_instance.foo", &v), 215 testAccCheckTags(&v.Tags, "foo", ""), 216 testAccCheckTags(&v.Tags, "bar", "baz"), 217 ), 218 }, 219 }, 220 }) 221 } 222 223 func TestAccInstance_privateIP(t *testing.T) { 224 var v ec2.Instance 225 226 testCheckPrivateIP := func() resource.TestCheckFunc { 227 return func(*terraform.State) error { 228 if v.PrivateIpAddress != "10.1.1.42" { 229 return fmt.Errorf("bad private IP: %s", v.PrivateIpAddress) 230 } 231 232 return nil 233 } 234 } 235 236 resource.Test(t, resource.TestCase{ 237 PreCheck: func() { testAccPreCheck(t) }, 238 Providers: testAccProviders, 239 CheckDestroy: testAccCheckInstanceDestroy, 240 Steps: []resource.TestStep{ 241 resource.TestStep{ 242 Config: testAccInstanceConfigPrivateIP, 243 Check: resource.ComposeTestCheckFunc( 244 testAccCheckInstanceExists("aws_instance.foo", &v), 245 testCheckPrivateIP(), 246 ), 247 }, 248 }, 249 }) 250 } 251 252 func TestAccInstance_associatePublicIPAndPrivateIP(t *testing.T) { 253 var v ec2.Instance 254 255 testCheckPrivateIP := func() resource.TestCheckFunc { 256 return func(*terraform.State) error { 257 if v.PrivateIpAddress != "10.1.1.42" { 258 return fmt.Errorf("bad private IP: %s", v.PrivateIpAddress) 259 } 260 261 return nil 262 } 263 } 264 265 resource.Test(t, resource.TestCase{ 266 PreCheck: func() { testAccPreCheck(t) }, 267 Providers: testAccProviders, 268 CheckDestroy: testAccCheckInstanceDestroy, 269 Steps: []resource.TestStep{ 270 resource.TestStep{ 271 Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP, 272 Check: resource.ComposeTestCheckFunc( 273 testAccCheckInstanceExists("aws_instance.foo", &v), 274 testCheckPrivateIP(), 275 ), 276 }, 277 }, 278 }) 279 } 280 281 func testAccCheckInstanceDestroy(s *terraform.State) error { 282 conn := testAccProvider.Meta().(*AWSClient).ec2conn 283 284 for _, rs := range s.RootModule().Resources { 285 if rs.Type != "aws_instance" { 286 continue 287 } 288 289 // Try to find the resource 290 resp, err := conn.Instances( 291 []string{rs.Primary.ID}, ec2.NewFilter()) 292 if err == nil { 293 if len(resp.Reservations) > 0 { 294 return fmt.Errorf("still exist.") 295 } 296 297 return nil 298 } 299 300 // Verify the error is what we want 301 ec2err, ok := err.(*ec2.Error) 302 if !ok { 303 return err 304 } 305 if ec2err.Code != "InvalidInstanceID.NotFound" { 306 return err 307 } 308 } 309 310 return nil 311 } 312 313 func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFunc { 314 return func(s *terraform.State) error { 315 rs, ok := s.RootModule().Resources[n] 316 if !ok { 317 return fmt.Errorf("Not found: %s", n) 318 } 319 320 if rs.Primary.ID == "" { 321 return fmt.Errorf("No ID is set") 322 } 323 324 conn := testAccProvider.Meta().(*AWSClient).ec2conn 325 resp, err := conn.Instances( 326 []string{rs.Primary.ID}, ec2.NewFilter()) 327 if err != nil { 328 return err 329 } 330 if len(resp.Reservations) == 0 { 331 return fmt.Errorf("Instance not found") 332 } 333 334 *i = resp.Reservations[0].Instances[0] 335 336 return nil 337 } 338 } 339 340 func TestInstanceTenancySchema(t *testing.T) { 341 actualSchema := resourceAwsInstance().Schema["tenancy"] 342 expectedSchema := &schema.Schema{ 343 Type: schema.TypeString, 344 Optional: true, 345 Computed: true, 346 ForceNew: true, 347 } 348 if !reflect.DeepEqual(actualSchema, expectedSchema) { 349 t.Fatalf( 350 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 351 actualSchema, 352 expectedSchema) 353 } 354 } 355 356 const testAccInstanceConfig = ` 357 resource "aws_security_group" "tf_test_foo" { 358 name = "tf_test_foo" 359 description = "foo" 360 361 ingress { 362 protocol = "icmp" 363 from_port = -1 364 to_port = -1 365 cidr_blocks = ["0.0.0.0/0"] 366 } 367 } 368 369 resource "aws_instance" "foo" { 370 # us-west-2 371 ami = "ami-4fccb37f" 372 availability_zone = "us-west-2a" 373 374 instance_type = "m1.small" 375 security_groups = ["${aws_security_group.tf_test_foo.name}"] 376 user_data = "foo" 377 } 378 ` 379 380 const testAccInstanceConfigBlockDevices = ` 381 resource "aws_instance" "foo" { 382 # us-west-2 383 ami = "ami-55a7ea65" 384 instance_type = "m1.small" 385 root_block_device { 386 device_name = "/dev/sda1" 387 volume_type = "gp2" 388 volume_size = 11 389 } 390 block_device { 391 device_name = "/dev/sdb" 392 volume_size = 9 393 } 394 } 395 ` 396 397 const testAccInstanceConfigSourceDestEnable = ` 398 resource "aws_vpc" "foo" { 399 cidr_block = "10.1.0.0/16" 400 } 401 402 resource "aws_subnet" "foo" { 403 cidr_block = "10.1.1.0/24" 404 vpc_id = "${aws_vpc.foo.id}" 405 } 406 407 resource "aws_instance" "foo" { 408 # us-west-2 409 ami = "ami-4fccb37f" 410 instance_type = "m1.small" 411 subnet_id = "${aws_subnet.foo.id}" 412 source_dest_check = true 413 } 414 ` 415 416 const testAccInstanceConfigSourceDestDisable = ` 417 resource "aws_vpc" "foo" { 418 cidr_block = "10.1.0.0/16" 419 } 420 421 resource "aws_subnet" "foo" { 422 cidr_block = "10.1.1.0/24" 423 vpc_id = "${aws_vpc.foo.id}" 424 } 425 426 resource "aws_instance" "foo" { 427 # us-west-2 428 ami = "ami-4fccb37f" 429 instance_type = "m1.small" 430 subnet_id = "${aws_subnet.foo.id}" 431 source_dest_check = false 432 } 433 ` 434 435 const testAccInstanceConfigVPC = ` 436 resource "aws_vpc" "foo" { 437 cidr_block = "10.1.0.0/16" 438 } 439 440 resource "aws_subnet" "foo" { 441 cidr_block = "10.1.1.0/24" 442 vpc_id = "${aws_vpc.foo.id}" 443 } 444 445 resource "aws_instance" "foo" { 446 # us-west-2 447 ami = "ami-4fccb37f" 448 instance_type = "m1.small" 449 subnet_id = "${aws_subnet.foo.id}" 450 associate_public_ip_address = true 451 tenancy = "dedicated" 452 } 453 ` 454 455 const testAccCheckInstanceConfigTags = ` 456 resource "aws_instance" "foo" { 457 ami = "ami-4fccb37f" 458 instance_type = "m1.small" 459 tags { 460 foo = "bar" 461 } 462 } 463 ` 464 465 const testAccCheckInstanceConfigTagsUpdate = ` 466 resource "aws_instance" "foo" { 467 ami = "ami-4fccb37f" 468 instance_type = "m1.small" 469 tags { 470 bar = "baz" 471 } 472 } 473 ` 474 475 const testAccInstanceConfigPrivateIP = ` 476 resource "aws_vpc" "foo" { 477 cidr_block = "10.1.0.0/16" 478 } 479 480 resource "aws_subnet" "foo" { 481 cidr_block = "10.1.1.0/24" 482 vpc_id = "${aws_vpc.foo.id}" 483 } 484 485 resource "aws_instance" "foo" { 486 ami = "ami-c5eabbf5" 487 instance_type = "t2.micro" 488 subnet_id = "${aws_subnet.foo.id}" 489 private_ip = "10.1.1.42" 490 } 491 ` 492 493 const testAccInstanceConfigAssociatePublicIPAndPrivateIP = ` 494 resource "aws_vpc" "foo" { 495 cidr_block = "10.1.0.0/16" 496 } 497 498 resource "aws_subnet" "foo" { 499 cidr_block = "10.1.1.0/24" 500 vpc_id = "${aws_vpc.foo.id}" 501 } 502 503 resource "aws_instance" "foo" { 504 ami = "ami-c5eabbf5" 505 instance_type = "t2.micro" 506 subnet_id = "${aws_subnet.foo.id}" 507 associate_public_ip_address = true 508 private_ip = "10.1.1.42" 509 } 510 `