github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/aws/resource_aws_launch_configuration_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "math/rand" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/aws/awserr" 13 "github.com/aws/aws-sdk-go/service/autoscaling" 14 "github.com/aws/aws-sdk-go/service/ec2" 15 "github.com/hashicorp/terraform/helper/acctest" 16 "github.com/hashicorp/terraform/helper/resource" 17 "github.com/hashicorp/terraform/terraform" 18 ) 19 20 func init() { 21 resource.AddTestSweepers("aws_launch_configuration", &resource.Sweeper{ 22 Name: "aws_launch_configuration", 23 Dependencies: []string{"aws_autoscaling_group"}, 24 F: testSweepLaunchConfigurations, 25 }) 26 } 27 28 func testSweepLaunchConfigurations(region string) error { 29 client, err := sharedClientForRegion(region) 30 if err != nil { 31 return fmt.Errorf("error getting client: %s", err) 32 } 33 autoscalingconn := client.(*AWSClient).autoscalingconn 34 35 resp, err := autoscalingconn.DescribeLaunchConfigurations(&autoscaling.DescribeLaunchConfigurationsInput{}) 36 if err != nil { 37 return fmt.Errorf("Error retrieving launch configuration: %s", err) 38 } 39 40 if len(resp.LaunchConfigurations) == 0 { 41 log.Print("[DEBUG] No aws launch configurations to sweep") 42 return nil 43 } 44 45 for _, lc := range resp.LaunchConfigurations { 46 var testOptGroup bool 47 for _, testName := range []string{"terraform-", "foobar"} { 48 if strings.HasPrefix(*lc.LaunchConfigurationName, testName) { 49 testOptGroup = true 50 } 51 } 52 53 if !testOptGroup { 54 continue 55 } 56 57 _, err := autoscalingconn.DeleteLaunchConfiguration( 58 &autoscaling.DeleteLaunchConfigurationInput{ 59 LaunchConfigurationName: lc.LaunchConfigurationName, 60 }) 61 if err != nil { 62 autoscalingerr, ok := err.(awserr.Error) 63 if ok && (autoscalingerr.Code() == "InvalidConfiguration.NotFound" || autoscalingerr.Code() == "ValidationError") { 64 log.Printf("[DEBUG] Launch configuration (%s) not found", *lc.LaunchConfigurationName) 65 return nil 66 } 67 68 return err 69 } 70 } 71 72 return nil 73 } 74 75 func TestAccAWSLaunchConfiguration_basic(t *testing.T) { 76 var conf autoscaling.LaunchConfiguration 77 78 resource.Test(t, resource.TestCase{ 79 PreCheck: func() { testAccPreCheck(t) }, 80 Providers: testAccProviders, 81 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 82 Steps: []resource.TestStep{ 83 { 84 Config: testAccAWSLaunchConfigurationNoNameConfig, 85 Check: resource.ComposeTestCheckFunc( 86 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), 87 testAccCheckAWSLaunchConfigurationGeneratedNamePrefix( 88 "aws_launch_configuration.bar", "terraform-"), 89 ), 90 }, 91 { 92 Config: testAccAWSLaunchConfigurationPrefixNameConfig, 93 Check: resource.ComposeTestCheckFunc( 94 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf), 95 testAccCheckAWSLaunchConfigurationGeneratedNamePrefix( 96 "aws_launch_configuration.baz", "baz-"), 97 ), 98 }, 99 }, 100 }) 101 } 102 103 func TestAccAWSLaunchConfiguration_withBlockDevices(t *testing.T) { 104 var conf autoscaling.LaunchConfiguration 105 106 resource.Test(t, resource.TestCase{ 107 PreCheck: func() { testAccPreCheck(t) }, 108 Providers: testAccProviders, 109 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 110 Steps: []resource.TestStep{ 111 { 112 Config: testAccAWSLaunchConfigurationConfig, 113 Check: resource.ComposeTestCheckFunc( 114 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), 115 testAccCheckAWSLaunchConfigurationAttributes(&conf), 116 resource.TestCheckResourceAttr( 117 "aws_launch_configuration.bar", "image_id", "ami-21f78e11"), 118 resource.TestCheckResourceAttr( 119 "aws_launch_configuration.bar", "instance_type", "m1.small"), 120 resource.TestCheckResourceAttr( 121 "aws_launch_configuration.bar", "associate_public_ip_address", "true"), 122 resource.TestCheckResourceAttr( 123 "aws_launch_configuration.bar", "spot_price", ""), 124 ), 125 }, 126 }, 127 }) 128 } 129 130 func TestAccAWSLaunchConfiguration_updateRootBlockDevice(t *testing.T) { 131 var conf autoscaling.LaunchConfiguration 132 rInt := acctest.RandInt() 133 134 resource.Test(t, resource.TestCase{ 135 PreCheck: func() { testAccPreCheck(t) }, 136 Providers: testAccProviders, 137 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 138 Steps: []resource.TestStep{ 139 { 140 Config: testAccAWSLaunchConfigurationConfigWithRootBlockDevice(rInt), 141 Check: resource.ComposeTestCheckFunc( 142 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), 143 resource.TestCheckResourceAttr( 144 "aws_launch_configuration.bar", "root_block_device.0.volume_size", "11"), 145 ), 146 }, 147 { 148 Config: testAccAWSLaunchConfigurationConfigWithRootBlockDeviceUpdated(rInt), 149 Check: resource.ComposeTestCheckFunc( 150 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), 151 resource.TestCheckResourceAttr( 152 "aws_launch_configuration.bar", "root_block_device.0.volume_size", "20"), 153 ), 154 }, 155 }, 156 }) 157 } 158 159 func TestAccAWSLaunchConfiguration_withSpotPrice(t *testing.T) { 160 var conf autoscaling.LaunchConfiguration 161 162 resource.Test(t, resource.TestCase{ 163 PreCheck: func() { testAccPreCheck(t) }, 164 Providers: testAccProviders, 165 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 166 Steps: []resource.TestStep{ 167 { 168 Config: testAccAWSLaunchConfigurationWithSpotPriceConfig, 169 Check: resource.ComposeTestCheckFunc( 170 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), 171 resource.TestCheckResourceAttr( 172 "aws_launch_configuration.bar", "spot_price", "0.01"), 173 ), 174 }, 175 }, 176 }) 177 } 178 179 func TestAccAWSLaunchConfiguration_withVpcClassicLink(t *testing.T) { 180 var vpc ec2.Vpc 181 var group ec2.SecurityGroup 182 var conf autoscaling.LaunchConfiguration 183 184 resource.Test(t, resource.TestCase{ 185 PreCheck: func() { testAccPreCheck(t) }, 186 Providers: testAccProviders, 187 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 188 Steps: []resource.TestStep{ 189 { 190 Config: testAccAWSLaunchConfigurationConfig_withVpcClassicLink, 191 Check: resource.ComposeTestCheckFunc( 192 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.foo", &conf), 193 testAccCheckVpcExists("aws_vpc.foo", &vpc), 194 testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group), 195 ), 196 }, 197 }, 198 }) 199 } 200 201 func TestAccAWSLaunchConfiguration_withIAMProfile(t *testing.T) { 202 var conf autoscaling.LaunchConfiguration 203 204 resource.Test(t, resource.TestCase{ 205 PreCheck: func() { testAccPreCheck(t) }, 206 Providers: testAccProviders, 207 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 208 Steps: []resource.TestStep{ 209 { 210 Config: testAccAWSLaunchConfigurationConfig_withIAMProfile, 211 Check: resource.ComposeTestCheckFunc( 212 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), 213 ), 214 }, 215 }, 216 }) 217 } 218 219 func testAccCheckAWSLaunchConfigurationWithEncryption(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc { 220 return func(s *terraform.State) error { 221 // Map out the block devices by name, which should be unique. 222 blockDevices := make(map[string]*autoscaling.BlockDeviceMapping) 223 for _, blockDevice := range conf.BlockDeviceMappings { 224 blockDevices[*blockDevice.DeviceName] = blockDevice 225 } 226 227 // Check if the root block device exists. 228 if _, ok := blockDevices["/dev/sda1"]; !ok { 229 return fmt.Errorf("block device doesn't exist: /dev/sda1") 230 } else if blockDevices["/dev/sda1"].Ebs.Encrypted != nil { 231 return fmt.Errorf("root device should not include value for Encrypted") 232 } 233 234 // Check if the secondary block device exists. 235 if _, ok := blockDevices["/dev/sdb"]; !ok { 236 return fmt.Errorf("block device doesn't exist: /dev/sdb") 237 } else if !*blockDevices["/dev/sdb"].Ebs.Encrypted { 238 return fmt.Errorf("block device isn't encrypted as expected: /dev/sdb") 239 } 240 241 return nil 242 } 243 } 244 245 func TestAccAWSLaunchConfiguration_withEncryption(t *testing.T) { 246 var conf autoscaling.LaunchConfiguration 247 248 resource.Test(t, resource.TestCase{ 249 PreCheck: func() { testAccPreCheck(t) }, 250 Providers: testAccProviders, 251 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 252 Steps: []resource.TestStep{ 253 { 254 Config: testAccAWSLaunchConfigurationWithEncryption, 255 Check: resource.ComposeTestCheckFunc( 256 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf), 257 testAccCheckAWSLaunchConfigurationWithEncryption(&conf), 258 ), 259 }, 260 }, 261 }) 262 } 263 264 func TestAccAWSLaunchConfiguration_updateEbsBlockDevices(t *testing.T) { 265 var conf autoscaling.LaunchConfiguration 266 267 resource.Test(t, resource.TestCase{ 268 PreCheck: func() { testAccPreCheck(t) }, 269 Providers: testAccProviders, 270 CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, 271 Steps: []resource.TestStep{ 272 { 273 Config: testAccAWSLaunchConfigurationWithEncryption, 274 Check: resource.ComposeTestCheckFunc( 275 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf), 276 resource.TestCheckResourceAttr( 277 "aws_launch_configuration.baz", "ebs_block_device.2764618555.volume_size", "9"), 278 ), 279 }, 280 { 281 Config: testAccAWSLaunchConfigurationWithEncryptionUpdated, 282 Check: resource.ComposeTestCheckFunc( 283 testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf), 284 resource.TestCheckResourceAttr( 285 "aws_launch_configuration.baz", "ebs_block_device.3859927736.volume_size", "10"), 286 ), 287 }, 288 }, 289 }) 290 } 291 292 func testAccCheckAWSLaunchConfigurationGeneratedNamePrefix( 293 resource, prefix string) resource.TestCheckFunc { 294 return func(s *terraform.State) error { 295 r, ok := s.RootModule().Resources[resource] 296 if !ok { 297 return fmt.Errorf("Resource not found") 298 } 299 name, ok := r.Primary.Attributes["name"] 300 if !ok { 301 return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes) 302 } 303 if !strings.HasPrefix(name, prefix) { 304 return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix) 305 } 306 return nil 307 } 308 } 309 310 func testAccCheckAWSLaunchConfigurationDestroy(s *terraform.State) error { 311 conn := testAccProvider.Meta().(*AWSClient).autoscalingconn 312 313 for _, rs := range s.RootModule().Resources { 314 if rs.Type != "aws_launch_configuration" { 315 continue 316 } 317 318 describe, err := conn.DescribeLaunchConfigurations( 319 &autoscaling.DescribeLaunchConfigurationsInput{ 320 LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)}, 321 }) 322 323 if err == nil { 324 if len(describe.LaunchConfigurations) != 0 && 325 *describe.LaunchConfigurations[0].LaunchConfigurationName == rs.Primary.ID { 326 return fmt.Errorf("Launch Configuration still exists") 327 } 328 } 329 330 // Verify the error 331 providerErr, ok := err.(awserr.Error) 332 if !ok { 333 return err 334 } 335 if providerErr.Code() != "InvalidLaunchConfiguration.NotFound" { 336 return err 337 } 338 } 339 340 return nil 341 } 342 343 func testAccCheckAWSLaunchConfigurationAttributes(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc { 344 return func(s *terraform.State) error { 345 if *conf.ImageId != "ami-21f78e11" { 346 return fmt.Errorf("Bad image_id: %s", *conf.ImageId) 347 } 348 349 if !strings.HasPrefix(*conf.LaunchConfigurationName, "terraform-") { 350 return fmt.Errorf("Bad name: %s", *conf.LaunchConfigurationName) 351 } 352 353 if *conf.InstanceType != "m1.small" { 354 return fmt.Errorf("Bad instance_type: %s", *conf.InstanceType) 355 } 356 357 // Map out the block devices by name, which should be unique. 358 blockDevices := make(map[string]*autoscaling.BlockDeviceMapping) 359 for _, blockDevice := range conf.BlockDeviceMappings { 360 blockDevices[*blockDevice.DeviceName] = blockDevice 361 } 362 363 // Check if the root block device exists. 364 if _, ok := blockDevices["/dev/sda1"]; !ok { 365 return fmt.Errorf("block device doesn't exist: /dev/sda1") 366 } 367 368 // Check if the secondary block device exists. 369 if _, ok := blockDevices["/dev/sdb"]; !ok { 370 return fmt.Errorf("block device doesn't exist: /dev/sdb") 371 } 372 373 // Check if the third block device exists. 374 if _, ok := blockDevices["/dev/sdc"]; !ok { 375 return fmt.Errorf("block device doesn't exist: /dev/sdc") 376 } 377 378 // Check if the secondary block device exists. 379 if _, ok := blockDevices["/dev/sdb"]; !ok { 380 return fmt.Errorf("block device doesn't exist: /dev/sdb") 381 } 382 383 return nil 384 } 385 } 386 387 func testAccCheckAWSLaunchConfigurationExists(n string, res *autoscaling.LaunchConfiguration) resource.TestCheckFunc { 388 return func(s *terraform.State) error { 389 rs, ok := s.RootModule().Resources[n] 390 if !ok { 391 return fmt.Errorf("Not found: %s", n) 392 } 393 394 if rs.Primary.ID == "" { 395 return fmt.Errorf("No Launch Configuration ID is set") 396 } 397 398 conn := testAccProvider.Meta().(*AWSClient).autoscalingconn 399 400 describeOpts := autoscaling.DescribeLaunchConfigurationsInput{ 401 LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)}, 402 } 403 describe, err := conn.DescribeLaunchConfigurations(&describeOpts) 404 405 if err != nil { 406 return err 407 } 408 409 if len(describe.LaunchConfigurations) != 1 || 410 *describe.LaunchConfigurations[0].LaunchConfigurationName != rs.Primary.ID { 411 return fmt.Errorf("Launch Configuration Group not found") 412 } 413 414 *res = *describe.LaunchConfigurations[0] 415 416 return nil 417 } 418 } 419 420 func testAccAWSLaunchConfigurationConfigWithRootBlockDevice(rInt int) string { 421 return fmt.Sprintf(` 422 resource "aws_launch_configuration" "bar" { 423 name_prefix = "tf-acc-test-%d" 424 image_id = "ami-21f78e11" 425 instance_type = "m1.small" 426 user_data = "foobar-user-data" 427 associate_public_ip_address = true 428 429 root_block_device { 430 volume_type = "gp2" 431 volume_size = 11 432 } 433 434 } 435 `, rInt) 436 } 437 438 func testAccAWSLaunchConfigurationConfigWithRootBlockDeviceUpdated(rInt int) string { 439 return fmt.Sprintf(` 440 resource "aws_launch_configuration" "bar" { 441 name_prefix = "tf-acc-test-%d" 442 image_id = "ami-21f78e11" 443 instance_type = "m1.small" 444 user_data = "foobar-user-data" 445 associate_public_ip_address = true 446 447 root_block_device { 448 volume_type = "gp2" 449 volume_size = 20 450 } 451 452 } 453 `, rInt) 454 } 455 456 var testAccAWSLaunchConfigurationConfig = fmt.Sprintf(` 457 resource "aws_launch_configuration" "bar" { 458 name = "terraform-test-%d" 459 image_id = "ami-21f78e11" 460 instance_type = "m1.small" 461 user_data = "foobar-user-data" 462 associate_public_ip_address = true 463 464 root_block_device { 465 volume_type = "gp2" 466 volume_size = 11 467 } 468 ebs_block_device { 469 device_name = "/dev/sdb" 470 volume_size = 9 471 } 472 ebs_block_device { 473 device_name = "/dev/sdc" 474 volume_size = 10 475 volume_type = "io1" 476 iops = 100 477 } 478 ephemeral_block_device { 479 device_name = "/dev/sde" 480 virtual_name = "ephemeral0" 481 } 482 } 483 `, rand.New(rand.NewSource(time.Now().UnixNano())).Int()) 484 485 var testAccAWSLaunchConfigurationWithSpotPriceConfig = fmt.Sprintf(` 486 resource "aws_launch_configuration" "bar" { 487 name = "terraform-test-%d" 488 image_id = "ami-21f78e11" 489 instance_type = "t1.micro" 490 spot_price = "0.01" 491 } 492 `, rand.New(rand.NewSource(time.Now().UnixNano())).Int()) 493 494 const testAccAWSLaunchConfigurationNoNameConfig = ` 495 resource "aws_launch_configuration" "bar" { 496 image_id = "ami-21f78e11" 497 instance_type = "t1.micro" 498 user_data = "foobar-user-data-change" 499 associate_public_ip_address = false 500 } 501 ` 502 503 const testAccAWSLaunchConfigurationPrefixNameConfig = ` 504 resource "aws_launch_configuration" "baz" { 505 name_prefix = "baz-" 506 image_id = "ami-21f78e11" 507 instance_type = "t1.micro" 508 user_data = "foobar-user-data-change" 509 associate_public_ip_address = false 510 } 511 ` 512 513 const testAccAWSLaunchConfigurationWithEncryption = ` 514 resource "aws_launch_configuration" "baz" { 515 image_id = "ami-5189a661" 516 instance_type = "t2.micro" 517 associate_public_ip_address = false 518 519 root_block_device { 520 volume_type = "gp2" 521 volume_size = 11 522 } 523 ebs_block_device { 524 device_name = "/dev/sdb" 525 volume_size = 9 526 encrypted = true 527 } 528 } 529 ` 530 531 const testAccAWSLaunchConfigurationWithEncryptionUpdated = ` 532 resource "aws_launch_configuration" "baz" { 533 image_id = "ami-5189a661" 534 instance_type = "t2.micro" 535 associate_public_ip_address = false 536 537 root_block_device { 538 volume_type = "gp2" 539 volume_size = 11 540 } 541 ebs_block_device { 542 device_name = "/dev/sdb" 543 volume_size = 10 544 encrypted = true 545 } 546 } 547 ` 548 549 const testAccAWSLaunchConfigurationConfig_withVpcClassicLink = ` 550 resource "aws_vpc" "foo" { 551 cidr_block = "10.0.0.0/16" 552 enable_classiclink = true 553 tags { 554 Name = "testAccAWSLaunchConfigurationConfig_withVpcClassicLink" 555 } 556 } 557 558 resource "aws_security_group" "foo" { 559 name = "foo" 560 vpc_id = "${aws_vpc.foo.id}" 561 } 562 563 resource "aws_launch_configuration" "foo" { 564 name = "TestAccAWSLaunchConfiguration_withVpcClassicLink" 565 image_id = "ami-21f78e11" 566 instance_type = "t1.micro" 567 568 vpc_classic_link_id = "${aws_vpc.foo.id}" 569 vpc_classic_link_security_groups = ["${aws_security_group.foo.id}"] 570 } 571 ` 572 573 const testAccAWSLaunchConfigurationConfig_withIAMProfile = ` 574 resource "aws_iam_role" "role" { 575 name = "TestAccAWSLaunchConfiguration-withIAMProfile" 576 assume_role_policy = <<EOF 577 { 578 "Version": "2012-10-17", 579 "Statement": [ 580 { 581 "Action": "sts:AssumeRole", 582 "Principal": { 583 "Service": "ec2.amazonaws.com" 584 }, 585 "Effect": "Allow", 586 "Sid": "" 587 } 588 ] 589 } 590 EOF 591 } 592 593 resource "aws_iam_instance_profile" "profile" { 594 name = "TestAccAWSLaunchConfiguration-withIAMProfile" 595 roles = ["${aws_iam_role.role.name}"] 596 } 597 598 resource "aws_launch_configuration" "bar" { 599 image_id = "ami-5189a661" 600 instance_type = "t2.nano" 601 iam_instance_profile = "${aws_iam_instance_profile.profile.name}" 602 } 603 `