github.com/sixgill/terraform@v0.9.0-beta2.0.20170316214032-033f6226ae50/builtin/providers/aws/resource_aws_opsworks_stack_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/hashicorp/terraform/helper/acctest" 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/terraform" 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/opsworks" 14 ) 15 16 /////////////////////////////// 17 //// Tests for the No-VPC case 18 /////////////////////////////// 19 20 func TestAccAWSOpsworksStackNoVpc(t *testing.T) { 21 stackName := fmt.Sprintf("tf-opsworks-acc-%d", acctest.RandInt()) 22 var opsstack opsworks.Stack 23 resource.Test(t, resource.TestCase{ 24 PreCheck: func() { testAccPreCheck(t) }, 25 Providers: testAccProviders, 26 CheckDestroy: testAccCheckAwsOpsworksStackDestroy, 27 Steps: []resource.TestStep{ 28 { 29 Config: testAccAwsOpsworksStackConfigNoVpcCreate(stackName), 30 Check: resource.ComposeTestCheckFunc( 31 testAccCheckAWSOpsworksStackExists( 32 "aws_opsworks_stack.tf-acc", false, &opsstack), 33 testAccCheckAWSOpsworksCreateStackAttributes( 34 &opsstack, "us-east-1a", stackName), 35 testAccAwsOpsworksStackCheckResourceAttrsCreate( 36 "us-east-1a", stackName), 37 ), 38 }, 39 }, 40 }) 41 } 42 43 func TestAccAWSOpsworksStackVpc(t *testing.T) { 44 stackName := fmt.Sprintf("tf-opsworks-acc-%d", acctest.RandInt()) 45 var opsstack opsworks.Stack 46 resource.Test(t, resource.TestCase{ 47 PreCheck: func() { testAccPreCheck(t) }, 48 Providers: testAccProviders, 49 CheckDestroy: testAccCheckAwsOpsworksStackDestroy, 50 Steps: []resource.TestStep{ 51 { 52 Config: testAccAwsOpsworksStackConfigVpcCreate(stackName), 53 Check: resource.ComposeTestCheckFunc( 54 testAccCheckAWSOpsworksStackExists( 55 "aws_opsworks_stack.tf-acc", true, &opsstack), 56 testAccCheckAWSOpsworksCreateStackAttributes( 57 &opsstack, "us-west-2a", stackName), 58 testAccAwsOpsworksStackCheckResourceAttrsCreate( 59 "us-west-2a", stackName), 60 ), 61 }, 62 { 63 Config: testAccAWSOpsworksStackConfigVpcUpdate(stackName), 64 Check: resource.ComposeTestCheckFunc( 65 testAccCheckAWSOpsworksStackExists( 66 "aws_opsworks_stack.tf-acc", true, &opsstack), 67 testAccCheckAWSOpsworksUpdateStackAttributes( 68 &opsstack, "us-west-2a", stackName), 69 testAccAwsOpsworksStackCheckResourceAttrsUpdate( 70 "us-west-2a", stackName), 71 ), 72 }, 73 }, 74 }) 75 } 76 77 //////////////////////////// 78 //// Checkers and Utilities 79 //////////////////////////// 80 81 func testAccAwsOpsworksStackCheckResourceAttrsCreate(zone, stackName string) resource.TestCheckFunc { 82 return resource.ComposeTestCheckFunc( 83 resource.TestCheckResourceAttr( 84 "aws_opsworks_stack.tf-acc", 85 "name", 86 stackName, 87 ), 88 resource.TestCheckResourceAttr( 89 "aws_opsworks_stack.tf-acc", 90 "default_availability_zone", 91 zone, 92 ), 93 resource.TestCheckResourceAttr( 94 "aws_opsworks_stack.tf-acc", 95 "default_os", 96 "Amazon Linux 2016.09", 97 ), 98 resource.TestCheckResourceAttr( 99 "aws_opsworks_stack.tf-acc", 100 "default_root_device_type", 101 "ebs", 102 ), 103 resource.TestCheckResourceAttr( 104 "aws_opsworks_stack.tf-acc", 105 "custom_json", 106 `{"key": "value"}`, 107 ), 108 resource.TestCheckResourceAttr( 109 "aws_opsworks_stack.tf-acc", 110 "configuration_manager_version", 111 "11.10", 112 ), 113 resource.TestCheckResourceAttr( 114 "aws_opsworks_stack.tf-acc", 115 "use_opsworks_security_groups", 116 "false", 117 ), 118 ) 119 } 120 121 func testAccAwsOpsworksStackCheckResourceAttrsUpdate(zone, stackName string) resource.TestCheckFunc { 122 return resource.ComposeTestCheckFunc( 123 resource.TestCheckResourceAttr( 124 "aws_opsworks_stack.tf-acc", 125 "name", 126 stackName, 127 ), 128 resource.TestCheckResourceAttr( 129 "aws_opsworks_stack.tf-acc", 130 "default_availability_zone", 131 zone, 132 ), 133 resource.TestCheckResourceAttr( 134 "aws_opsworks_stack.tf-acc", 135 "default_os", 136 "Amazon Linux 2015.09", 137 ), 138 resource.TestCheckResourceAttr( 139 "aws_opsworks_stack.tf-acc", 140 "default_root_device_type", 141 "ebs", 142 ), 143 resource.TestCheckResourceAttr( 144 "aws_opsworks_stack.tf-acc", 145 "custom_json", 146 `{"key": "value"}`, 147 ), 148 resource.TestCheckResourceAttr( 149 "aws_opsworks_stack.tf-acc", 150 "configuration_manager_version", 151 "11.10", 152 ), 153 resource.TestCheckResourceAttr( 154 "aws_opsworks_stack.tf-acc", 155 "use_opsworks_security_groups", 156 "false", 157 ), 158 resource.TestCheckResourceAttr( 159 "aws_opsworks_stack.tf-acc", 160 "use_custom_cookbooks", 161 "true", 162 ), 163 resource.TestCheckResourceAttr( 164 "aws_opsworks_stack.tf-acc", 165 "manage_berkshelf", 166 "true", 167 ), 168 resource.TestCheckResourceAttr( 169 "aws_opsworks_stack.tf-acc", 170 "custom_cookbooks_source.0.type", 171 "git", 172 ), 173 resource.TestCheckResourceAttr( 174 "aws_opsworks_stack.tf-acc", 175 "custom_cookbooks_source.0.revision", 176 "master", 177 ), 178 resource.TestCheckResourceAttr( 179 "aws_opsworks_stack.tf-acc", 180 "custom_cookbooks_source.0.url", 181 "https://github.com/aws/opsworks-example-cookbooks.git", 182 ), 183 ) 184 } 185 186 func testAccCheckAWSOpsworksStackExists( 187 n string, vpc bool, opsstack *opsworks.Stack) resource.TestCheckFunc { 188 return func(s *terraform.State) error { 189 rs, ok := s.RootModule().Resources[n] 190 if !ok { 191 return fmt.Errorf("Not found: %s", n) 192 } 193 194 if rs.Primary.ID == "" { 195 return fmt.Errorf("No ID is set") 196 } 197 198 conn := testAccProvider.Meta().(*AWSClient).opsworksconn 199 200 params := &opsworks.DescribeStacksInput{ 201 StackIds: []*string{aws.String(rs.Primary.ID)}, 202 } 203 resp, err := conn.DescribeStacks(params) 204 205 if err != nil { 206 return err 207 } 208 209 if v := len(resp.Stacks); v != 1 { 210 return fmt.Errorf("Expected 1 response returned, got %d", v) 211 } 212 213 *opsstack = *resp.Stacks[0] 214 215 if vpc { 216 if rs.Primary.Attributes["vpc_id"] != *opsstack.VpcId { 217 return fmt.Errorf("VPCID Got %s, expected %s", *opsstack.VpcId, rs.Primary.Attributes["vpc_id"]) 218 } 219 if rs.Primary.Attributes["default_subnet_id"] != *opsstack.DefaultSubnetId { 220 return fmt.Errorf("Default subnet Id Got %s, expected %s", *opsstack.DefaultSubnetId, rs.Primary.Attributes["default_subnet_id"]) 221 } 222 } 223 224 return nil 225 } 226 } 227 228 func testAccCheckAWSOpsworksCreateStackAttributes( 229 opsstack *opsworks.Stack, zone, stackName string) resource.TestCheckFunc { 230 return func(s *terraform.State) error { 231 if *opsstack.Name != stackName { 232 return fmt.Errorf("Unnexpected stackName: %s", *opsstack.Name) 233 } 234 235 if *opsstack.DefaultAvailabilityZone != zone { 236 return fmt.Errorf("Unnexpected DefaultAvailabilityZone: %s", *opsstack.DefaultAvailabilityZone) 237 } 238 239 if *opsstack.DefaultOs != "Amazon Linux 2016.09" { 240 return fmt.Errorf("Unnexpected stackName: %s", *opsstack.DefaultOs) 241 } 242 243 if *opsstack.DefaultRootDeviceType != "ebs" { 244 return fmt.Errorf("Unnexpected DefaultRootDeviceType: %s", *opsstack.DefaultRootDeviceType) 245 } 246 247 if *opsstack.CustomJson != `{"key": "value"}` { 248 return fmt.Errorf("Unnexpected CustomJson: %s", *opsstack.CustomJson) 249 } 250 251 if *opsstack.ConfigurationManager.Version != "11.10" { 252 return fmt.Errorf("Unnexpected Version: %s", *opsstack.ConfigurationManager.Version) 253 } 254 255 if *opsstack.UseOpsworksSecurityGroups { 256 return fmt.Errorf("Unnexpected UseOpsworksSecurityGroups: %t", *opsstack.UseOpsworksSecurityGroups) 257 } 258 259 return nil 260 } 261 } 262 263 func testAccCheckAWSOpsworksUpdateStackAttributes( 264 opsstack *opsworks.Stack, zone, stackName string) resource.TestCheckFunc { 265 return func(s *terraform.State) error { 266 if *opsstack.Name != stackName { 267 return fmt.Errorf("Unnexpected stackName: %s", *opsstack.Name) 268 } 269 270 if *opsstack.DefaultAvailabilityZone != zone { 271 return fmt.Errorf("Unnexpected DefaultAvailabilityZone: %s", *opsstack.DefaultAvailabilityZone) 272 } 273 274 if *opsstack.DefaultOs != "Amazon Linux 2015.09" { 275 return fmt.Errorf("Unnexpected stackName: %s", *opsstack.DefaultOs) 276 } 277 278 if *opsstack.DefaultRootDeviceType != "ebs" { 279 return fmt.Errorf("Unnexpected DefaultRootDeviceType: %s", *opsstack.DefaultRootDeviceType) 280 } 281 282 if *opsstack.CustomJson != `{"key": "value"}` { 283 return fmt.Errorf("Unnexpected CustomJson: %s", *opsstack.CustomJson) 284 } 285 286 if *opsstack.ConfigurationManager.Version != "11.10" { 287 return fmt.Errorf("Unnexpected Version: %s", *opsstack.ConfigurationManager.Version) 288 } 289 290 if !*opsstack.UseCustomCookbooks { 291 return fmt.Errorf("Unnexpected UseCustomCookbooks: %t", *opsstack.UseCustomCookbooks) 292 } 293 294 if !*opsstack.ChefConfiguration.ManageBerkshelf { 295 return fmt.Errorf("Unnexpected ManageBerkshelf: %t", *opsstack.ChefConfiguration.ManageBerkshelf) 296 } 297 298 if *opsstack.CustomCookbooksSource.Type != "git" { 299 return fmt.Errorf("Unnexpected *opsstack.CustomCookbooksSource.Type: %s", *opsstack.CustomCookbooksSource.Type) 300 } 301 302 if *opsstack.CustomCookbooksSource.Revision != "master" { 303 return fmt.Errorf("Unnexpected *opsstack.CustomCookbooksSource.Type: %s", *opsstack.CustomCookbooksSource.Revision) 304 } 305 306 if *opsstack.CustomCookbooksSource.Url != "https://github.com/aws/opsworks-example-cookbooks.git" { 307 return fmt.Errorf("Unnexpected *opsstack.CustomCookbooksSource.Type: %s", *opsstack.CustomCookbooksSource.Url) 308 } 309 310 return nil 311 } 312 } 313 314 func testAccCheckAwsOpsworksStackDestroy(s *terraform.State) error { 315 opsworksconn := testAccProvider.Meta().(*AWSClient).opsworksconn 316 for _, rs := range s.RootModule().Resources { 317 if rs.Type != "aws_opsworks_stack" { 318 continue 319 } 320 321 req := &opsworks.DescribeStacksInput{ 322 StackIds: []*string{ 323 aws.String(rs.Primary.ID), 324 }, 325 } 326 327 _, err := opsworksconn.DescribeStacks(req) 328 if err != nil { 329 if awserr, ok := err.(awserr.Error); ok { 330 if awserr.Code() == "ResourceNotFoundException" { 331 // not found, all good 332 return nil 333 } 334 } 335 return err 336 } 337 } 338 return fmt.Errorf("Fall through error for OpsWorks stack test") 339 } 340 341 ////////////////////////////////////////////////// 342 //// Helper configs for the necessary IAM objects 343 ////////////////////////////////////////////////// 344 345 func testAccAwsOpsworksStackConfigNoVpcCreate(name string) string { 346 return fmt.Sprintf(` 347 provider "aws" { 348 region = "us-east-1" 349 } 350 resource "aws_opsworks_stack" "tf-acc" { 351 name = "%s" 352 region = "us-east-1" 353 service_role_arn = "${aws_iam_role.opsworks_service.arn}" 354 default_instance_profile_arn = "${aws_iam_instance_profile.opsworks_instance.arn}" 355 default_availability_zone = "us-east-1a" 356 default_os = "Amazon Linux 2016.09" 357 default_root_device_type = "ebs" 358 custom_json = "{\"key\": \"value\"}" 359 configuration_manager_version = "11.10" 360 use_opsworks_security_groups = false 361 } 362 363 resource "aws_iam_role" "opsworks_service" { 364 name = "%s_opsworks_service" 365 assume_role_policy = <<EOT 366 { 367 "Version": "2008-10-17", 368 "Statement": [ 369 { 370 "Sid": "", 371 "Effect": "Allow", 372 "Principal": { 373 "Service": "opsworks.amazonaws.com" 374 }, 375 "Action": "sts:AssumeRole" 376 } 377 ] 378 } 379 EOT 380 } 381 382 resource "aws_iam_role_policy" "opsworks_service" { 383 name = "%s_opsworks_service" 384 role = "${aws_iam_role.opsworks_service.id}" 385 policy = <<EOT 386 { 387 "Statement": [ 388 { 389 "Action": [ 390 "ec2:*", 391 "iam:PassRole", 392 "cloudwatch:GetMetricStatistics", 393 "elasticloadbalancing:*", 394 "rds:*" 395 ], 396 "Effect": "Allow", 397 "Resource": ["*"] 398 } 399 ] 400 } 401 EOT 402 } 403 404 resource "aws_iam_role" "opsworks_instance" { 405 name = "%s_opsworks_instance" 406 assume_role_policy = <<EOT 407 { 408 "Version": "2008-10-17", 409 "Statement": [ 410 { 411 "Sid": "", 412 "Effect": "Allow", 413 "Principal": { 414 "Service": "ec2.amazonaws.com" 415 }, 416 "Action": "sts:AssumeRole" 417 } 418 ] 419 } 420 EOT 421 } 422 423 resource "aws_iam_instance_profile" "opsworks_instance" { 424 name = "%s_opsworks_instance" 425 roles = ["${aws_iam_role.opsworks_instance.name}"] 426 }`, name, name, name, name, name) 427 } 428 429 //////////////////////////// 430 //// Tests for the VPC case 431 //////////////////////////// 432 433 func testAccAwsOpsworksStackConfigVpcCreate(name string) string { 434 return fmt.Sprintf(` 435 resource "aws_vpc" "tf-acc" { 436 cidr_block = "10.3.5.0/24" 437 } 438 resource "aws_subnet" "tf-acc" { 439 vpc_id = "${aws_vpc.tf-acc.id}" 440 cidr_block = "${aws_vpc.tf-acc.cidr_block}" 441 availability_zone = "us-west-2a" 442 } 443 resource "aws_opsworks_stack" "tf-acc" { 444 name = "%s" 445 region = "us-west-2" 446 vpc_id = "${aws_vpc.tf-acc.id}" 447 default_subnet_id = "${aws_subnet.tf-acc.id}" 448 service_role_arn = "${aws_iam_role.opsworks_service.arn}" 449 default_instance_profile_arn = "${aws_iam_instance_profile.opsworks_instance.arn}" 450 default_os = "Amazon Linux 2016.09" 451 default_root_device_type = "ebs" 452 custom_json = "{\"key\": \"value\"}" 453 configuration_manager_version = "11.10" 454 use_opsworks_security_groups = false 455 } 456 457 resource "aws_iam_role" "opsworks_service" { 458 name = "%s_opsworks_service" 459 assume_role_policy = <<EOT 460 { 461 "Version": "2008-10-17", 462 "Statement": [ 463 { 464 "Sid": "", 465 "Effect": "Allow", 466 "Principal": { 467 "Service": "opsworks.amazonaws.com" 468 }, 469 "Action": "sts:AssumeRole" 470 } 471 ] 472 } 473 EOT 474 } 475 476 resource "aws_iam_role_policy" "opsworks_service" { 477 name = "%s_opsworks_service" 478 role = "${aws_iam_role.opsworks_service.id}" 479 policy = <<EOT 480 { 481 "Statement": [ 482 { 483 "Action": [ 484 "ec2:*", 485 "iam:PassRole", 486 "cloudwatch:GetMetricStatistics", 487 "elasticloadbalancing:*", 488 "rds:*" 489 ], 490 "Effect": "Allow", 491 "Resource": ["*"] 492 } 493 ] 494 } 495 EOT 496 } 497 498 resource "aws_iam_role" "opsworks_instance" { 499 name = "%s_opsworks_instance" 500 assume_role_policy = <<EOT 501 { 502 "Version": "2008-10-17", 503 "Statement": [ 504 { 505 "Sid": "", 506 "Effect": "Allow", 507 "Principal": { 508 "Service": "ec2.amazonaws.com" 509 }, 510 "Action": "sts:AssumeRole" 511 } 512 ] 513 } 514 EOT 515 } 516 517 resource "aws_iam_instance_profile" "opsworks_instance" { 518 name = "%s_opsworks_instance" 519 roles = ["${aws_iam_role.opsworks_instance.name}"] 520 } 521 `, name, name, name, name, name) 522 } 523 524 func testAccAWSOpsworksStackConfigVpcUpdate(name string) string { 525 return fmt.Sprintf(` 526 resource "aws_vpc" "tf-acc" { 527 cidr_block = "10.3.5.0/24" 528 } 529 resource "aws_subnet" "tf-acc" { 530 vpc_id = "${aws_vpc.tf-acc.id}" 531 cidr_block = "${aws_vpc.tf-acc.cidr_block}" 532 availability_zone = "us-west-2a" 533 } 534 resource "aws_opsworks_stack" "tf-acc" { 535 name = "%s" 536 region = "us-west-2" 537 vpc_id = "${aws_vpc.tf-acc.id}" 538 default_subnet_id = "${aws_subnet.tf-acc.id}" 539 service_role_arn = "${aws_iam_role.opsworks_service.arn}" 540 default_instance_profile_arn = "${aws_iam_instance_profile.opsworks_instance.arn}" 541 default_os = "Amazon Linux 2015.09" 542 default_root_device_type = "ebs" 543 custom_json = "{\"key\": \"value\"}" 544 configuration_manager_version = "11.10" 545 use_opsworks_security_groups = false 546 use_custom_cookbooks = true 547 manage_berkshelf = true 548 custom_cookbooks_source { 549 type = "git" 550 revision = "master" 551 url = "https://github.com/aws/opsworks-example-cookbooks.git" 552 } 553 } 554 555 resource "aws_iam_role" "opsworks_service" { 556 name = "%s_opsworks_service" 557 assume_role_policy = <<EOT 558 { 559 "Version": "2008-10-17", 560 "Statement": [ 561 { 562 "Sid": "", 563 "Effect": "Allow", 564 "Principal": { 565 "Service": "opsworks.amazonaws.com" 566 }, 567 "Action": "sts:AssumeRole" 568 } 569 ] 570 } 571 EOT 572 } 573 574 resource "aws_iam_role_policy" "opsworks_service" { 575 name = "%s_opsworks_service" 576 role = "${aws_iam_role.opsworks_service.id}" 577 policy = <<EOT 578 { 579 "Statement": [ 580 { 581 "Action": [ 582 "ec2:*", 583 "iam:PassRole", 584 "cloudwatch:GetMetricStatistics", 585 "elasticloadbalancing:*", 586 "rds:*" 587 ], 588 "Effect": "Allow", 589 "Resource": ["*"] 590 } 591 ] 592 } 593 EOT 594 } 595 596 resource "aws_iam_role" "opsworks_instance" { 597 name = "%s_opsworks_instance" 598 assume_role_policy = <<EOT 599 { 600 "Version": "2008-10-17", 601 "Statement": [ 602 { 603 "Sid": "", 604 "Effect": "Allow", 605 "Principal": { 606 "Service": "ec2.amazonaws.com" 607 }, 608 "Action": "sts:AssumeRole" 609 } 610 ] 611 } 612 EOT 613 } 614 615 resource "aws_iam_instance_profile" "opsworks_instance" { 616 name = "%s_opsworks_instance" 617 roles = ["${aws_iam_role.opsworks_instance.name}"] 618 } 619 620 `, name, name, name, name, name) 621 }