github.com/jdextraze/terraform@v0.6.17-0.20160511153921-e33847c8a8af/builtin/providers/aws/resource_aws_codedeploy_deployment_group_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "reflect" 6 "regexp" 7 "sort" 8 "testing" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/codedeploy" 13 "github.com/hashicorp/terraform/helper/resource" 14 "github.com/hashicorp/terraform/helper/schema" 15 "github.com/hashicorp/terraform/terraform" 16 ) 17 18 func TestAccAWSCodeDeployDeploymentGroup_basic(t *testing.T) { 19 var group codedeploy.DeploymentGroupInfo 20 21 resource.Test(t, resource.TestCase{ 22 PreCheck: func() { testAccPreCheck(t) }, 23 Providers: testAccProviders, 24 CheckDestroy: testAccCheckAWSCodeDeployDeploymentGroupDestroy, 25 Steps: []resource.TestStep{ 26 resource.TestStep{ 27 Config: testAccAWSCodeDeployDeploymentGroup, 28 Check: resource.ComposeTestCheckFunc( 29 testAccCheckAWSCodeDeployDeploymentGroupExists("aws_codedeploy_deployment_group.foo", &group), 30 resource.TestCheckResourceAttr( 31 "aws_codedeploy_deployment_group.foo", "app_name", "foo_app"), 32 resource.TestCheckResourceAttr( 33 "aws_codedeploy_deployment_group.foo", "deployment_group_name", "foo"), 34 resource.TestCheckResourceAttr( 35 "aws_codedeploy_deployment_group.foo", "deployment_config_name", "CodeDeployDefault.OneAtATime"), 36 37 resource.TestCheckResourceAttr( 38 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.#", "1"), 39 resource.TestCheckResourceAttr( 40 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.2916377465.key", "filterkey"), 41 resource.TestCheckResourceAttr( 42 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.2916377465.type", "KEY_AND_VALUE"), 43 resource.TestCheckResourceAttr( 44 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.2916377465.value", "filtervalue"), 45 ), 46 }, 47 resource.TestStep{ 48 Config: testAccAWSCodeDeployDeploymentGroupModified, 49 Check: resource.ComposeTestCheckFunc( 50 testAccCheckAWSCodeDeployDeploymentGroupExists("aws_codedeploy_deployment_group.foo", &group), 51 resource.TestCheckResourceAttr( 52 "aws_codedeploy_deployment_group.foo", "app_name", "foo_app"), 53 resource.TestCheckResourceAttr( 54 "aws_codedeploy_deployment_group.foo", "deployment_group_name", "bar"), 55 resource.TestCheckResourceAttr( 56 "aws_codedeploy_deployment_group.foo", "deployment_config_name", "CodeDeployDefault.OneAtATime"), 57 58 resource.TestCheckResourceAttr( 59 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.#", "1"), 60 resource.TestCheckResourceAttr( 61 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.2369538975.key", "filterkey"), 62 resource.TestCheckResourceAttr( 63 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.2369538975.type", "KEY_AND_VALUE"), 64 resource.TestCheckResourceAttr( 65 "aws_codedeploy_deployment_group.foo", "ec2_tag_filter.2369538975.value", "anotherfiltervalue"), 66 ), 67 }, 68 }, 69 }) 70 } 71 72 func TestAccAWSCodeDeployDeploymentGroup_triggerConfiguration_basic(t *testing.T) { 73 var group codedeploy.DeploymentGroupInfo 74 75 resource.Test(t, resource.TestCase{ 76 PreCheck: func() { testAccPreCheck(t) }, 77 Providers: testAccProviders, 78 CheckDestroy: testAccCheckAWSCodeDeployDeploymentGroupDestroy, 79 Steps: []resource.TestStep{ 80 resource.TestStep{ 81 Config: testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_create, 82 Check: resource.ComposeTestCheckFunc( 83 testAccCheckAWSCodeDeployDeploymentGroupExists("aws_codedeploy_deployment_group.foo_group", &group), 84 resource.TestCheckResourceAttr( 85 "aws_codedeploy_deployment_group.foo_group", "app_name", "foo-app"), 86 resource.TestCheckResourceAttr( 87 "aws_codedeploy_deployment_group.foo_group", "deployment_group_name", "foo-group"), 88 testAccCheckTriggerEvents(&group, "foo-trigger", []string{ 89 "DeploymentFailure", 90 }), 91 ), 92 }, 93 resource.TestStep{ 94 Config: testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_update, 95 Check: resource.ComposeTestCheckFunc( 96 testAccCheckAWSCodeDeployDeploymentGroupExists("aws_codedeploy_deployment_group.foo_group", &group), 97 resource.TestCheckResourceAttr( 98 "aws_codedeploy_deployment_group.foo_group", "app_name", "foo-app"), 99 resource.TestCheckResourceAttr( 100 "aws_codedeploy_deployment_group.foo_group", "deployment_group_name", "foo-group"), 101 testAccCheckTriggerEvents(&group, "foo-trigger", []string{ 102 "DeploymentFailure", 103 "DeploymentSuccess", 104 }), 105 ), 106 }, 107 }, 108 }) 109 } 110 111 func TestAccAWSCodeDeployDeploymentGroup_triggerConfiguration_multiple(t *testing.T) { 112 var group codedeploy.DeploymentGroupInfo 113 114 resource.Test(t, resource.TestCase{ 115 PreCheck: func() { testAccPreCheck(t) }, 116 Providers: testAccProviders, 117 CheckDestroy: testAccCheckAWSCodeDeployDeploymentGroupDestroy, 118 Steps: []resource.TestStep{ 119 resource.TestStep{ 120 Config: testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_createMultiple, 121 Check: resource.ComposeTestCheckFunc( 122 testAccCheckAWSCodeDeployDeploymentGroupExists("aws_codedeploy_deployment_group.foo_group", &group), 123 resource.TestCheckResourceAttr( 124 "aws_codedeploy_deployment_group.foo_group", "app_name", "foo-app"), 125 resource.TestCheckResourceAttr( 126 "aws_codedeploy_deployment_group.foo_group", "deployment_group_name", "foo-group"), 127 testAccCheckTriggerEvents(&group, "foo-trigger", []string{ 128 "DeploymentFailure", 129 }), 130 testAccCheckTriggerEvents(&group, "bar-trigger", []string{ 131 "InstanceFailure", 132 }), 133 testAccCheckTriggerTargetArn(&group, "bar-trigger", 134 regexp.MustCompile("^arn:aws:sns:[^:]+:[0-9]{12}:bar-topic$")), 135 ), 136 }, 137 resource.TestStep{ 138 Config: testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_updateMultiple, 139 Check: resource.ComposeTestCheckFunc( 140 testAccCheckAWSCodeDeployDeploymentGroupExists("aws_codedeploy_deployment_group.foo_group", &group), 141 resource.TestCheckResourceAttr( 142 "aws_codedeploy_deployment_group.foo_group", "app_name", "foo-app"), 143 resource.TestCheckResourceAttr( 144 "aws_codedeploy_deployment_group.foo_group", "deployment_group_name", "foo-group"), 145 testAccCheckTriggerEvents(&group, "foo-trigger", []string{ 146 "DeploymentFailure", 147 "DeploymentStart", 148 "DeploymentStop", 149 "DeploymentSuccess", 150 }), 151 testAccCheckTriggerEvents(&group, "bar-trigger", []string{ 152 "InstanceFailure", 153 }), 154 testAccCheckTriggerTargetArn(&group, "bar-trigger", 155 regexp.MustCompile("^arn:aws:sns:[^:]+:[0-9]{12}:baz-topic$")), 156 ), 157 }, 158 }, 159 }) 160 } 161 162 func TestValidateAWSCodeDeployTriggerEvent(t *testing.T) { 163 cases := []struct { 164 Value string 165 ErrCount int 166 }{ 167 { 168 Value: "DeploymentStart", 169 ErrCount: 0, 170 }, 171 { 172 Value: "DeploymentStop", 173 ErrCount: 0, 174 }, 175 { 176 Value: "DeploymentSuccess", 177 ErrCount: 0, 178 }, 179 { 180 Value: "DeploymentFailure", 181 ErrCount: 0, 182 }, 183 { 184 Value: "InstanceStart", 185 ErrCount: 0, 186 }, 187 { 188 Value: "InstanceSuccess", 189 ErrCount: 0, 190 }, 191 { 192 Value: "InstanceFailure", 193 ErrCount: 0, 194 }, 195 { 196 Value: "DeploymentStarts", 197 ErrCount: 1, 198 }, 199 { 200 Value: "InstanceFail", 201 ErrCount: 1, 202 }, 203 { 204 Value: "Foo", 205 ErrCount: 1, 206 }, 207 { 208 Value: "", 209 ErrCount: 1, 210 }, 211 } 212 213 for _, tc := range cases { 214 _, errors := validateTriggerEvent(tc.Value, "trigger_event") 215 if len(errors) != tc.ErrCount { 216 t.Fatalf("Trigger event validation failed for event type %q: %q", tc.Value, errors) 217 } 218 } 219 } 220 221 func TestBuildTriggerConfigs(t *testing.T) { 222 input := []interface{}{ 223 map[string]interface{}{ 224 "trigger_events": schema.NewSet(schema.HashString, []interface{}{ 225 "DeploymentFailure", 226 }), 227 "trigger_name": "foo-trigger", 228 "trigger_target_arn": "arn:aws:sns:us-west-2:123456789012:foo-topic", 229 }, 230 } 231 232 expected := []*codedeploy.TriggerConfig{ 233 &codedeploy.TriggerConfig{ 234 TriggerEvents: []*string{ 235 aws.String("DeploymentFailure"), 236 }, 237 TriggerName: aws.String("foo-trigger"), 238 TriggerTargetArn: aws.String("arn:aws:sns:us-west-2:123456789012:foo-topic"), 239 }, 240 } 241 242 actual := buildTriggerConfigs(input) 243 244 if !reflect.DeepEqual(actual, expected) { 245 t.Fatalf("buildTriggerConfigs output is not correct.\nGot:\n%#v\nExpected:\n%#v\n", 246 actual, expected) 247 } 248 } 249 250 func TestTriggerConfigsToMap(t *testing.T) { 251 input := []*codedeploy.TriggerConfig{ 252 &codedeploy.TriggerConfig{ 253 TriggerEvents: []*string{ 254 aws.String("DeploymentFailure"), 255 aws.String("InstanceFailure"), 256 }, 257 TriggerName: aws.String("bar-trigger"), 258 TriggerTargetArn: aws.String("arn:aws:sns:us-west-2:123456789012:bar-topic"), 259 }, 260 } 261 262 expected := map[string]interface{}{ 263 "trigger_events": schema.NewSet(schema.HashString, []interface{}{ 264 "DeploymentFailure", 265 "InstanceFailure", 266 }), 267 "trigger_name": "bar-trigger", 268 "trigger_target_arn": "arn:aws:sns:us-west-2:123456789012:bar-topic", 269 } 270 271 actual := triggerConfigsToMap(input)[0] 272 273 fatal := false 274 275 if actual["trigger_name"] != expected["trigger_name"] { 276 fatal = true 277 } 278 279 if actual["trigger_target_arn"] != expected["trigger_target_arn"] { 280 fatal = true 281 } 282 283 actualEvents := actual["trigger_events"].(*schema.Set) 284 expectedEvents := expected["trigger_events"].(*schema.Set) 285 if !actualEvents.Equal(expectedEvents) { 286 fatal = true 287 } 288 289 if fatal { 290 t.Fatalf("triggerConfigsToMap output is not correct.\nGot:\n%#v\nExpected:\n%#v\n", 291 actual, expected) 292 } 293 } 294 295 func testAccCheckTriggerEvents(group *codedeploy.DeploymentGroupInfo, triggerName string, expectedEvents []string) resource.TestCheckFunc { 296 return func(s *terraform.State) error { 297 298 for _, actual := range group.TriggerConfigurations { 299 if *actual.TriggerName == triggerName { 300 301 numberOfEvents := len(actual.TriggerEvents) 302 if numberOfEvents != len(expectedEvents) { 303 return fmt.Errorf("Trigger events do not match. Expected: %d. Got: %d.", 304 len(expectedEvents), numberOfEvents) 305 } 306 307 actualEvents := make([]string, 0, numberOfEvents) 308 for _, event := range actual.TriggerEvents { 309 actualEvents = append(actualEvents, *event) 310 } 311 sort.Strings(actualEvents) 312 313 if !reflect.DeepEqual(actualEvents, expectedEvents) { 314 return fmt.Errorf("Trigger events do not match.\nExpected: %v\nGot: %v\n", 315 expectedEvents, actualEvents) 316 } 317 break 318 } 319 } 320 return nil 321 } 322 } 323 324 func testAccCheckTriggerTargetArn(group *codedeploy.DeploymentGroupInfo, triggerName string, r *regexp.Regexp) resource.TestCheckFunc { 325 return func(s *terraform.State) error { 326 for _, actual := range group.TriggerConfigurations { 327 if *actual.TriggerName == triggerName { 328 if !r.MatchString(*actual.TriggerTargetArn) { 329 return fmt.Errorf("Trigger target arn does not match regular expression.\nRegex: %v\nTriggerTargetArn: %v\n", 330 r, *actual.TriggerTargetArn) 331 } 332 break 333 } 334 } 335 return nil 336 } 337 } 338 339 func testAccCheckAWSCodeDeployDeploymentGroupDestroy(s *terraform.State) error { 340 conn := testAccProvider.Meta().(*AWSClient).codedeployconn 341 342 for _, rs := range s.RootModule().Resources { 343 if rs.Type != "aws_codedeploy_deployment_group" { 344 continue 345 } 346 347 resp, err := conn.GetDeploymentGroup(&codedeploy.GetDeploymentGroupInput{ 348 ApplicationName: aws.String(rs.Primary.Attributes["app_name"]), 349 DeploymentGroupName: aws.String(rs.Primary.Attributes["deployment_group_name"]), 350 }) 351 352 if ae, ok := err.(awserr.Error); ok && ae.Code() == "ApplicationDoesNotExistException" { 353 continue 354 } 355 356 if err == nil { 357 if resp.DeploymentGroupInfo.DeploymentGroupName != nil { 358 return fmt.Errorf("CodeDeploy deployment group still exists:\n%#v", *resp.DeploymentGroupInfo.DeploymentGroupName) 359 } 360 } 361 362 return err 363 } 364 365 return nil 366 } 367 368 func testAccCheckAWSCodeDeployDeploymentGroupExists(name string, group *codedeploy.DeploymentGroupInfo) resource.TestCheckFunc { 369 return func(s *terraform.State) error { 370 rs, ok := s.RootModule().Resources[name] 371 if !ok { 372 return fmt.Errorf("Not found: %s", name) 373 } 374 375 conn := testAccProvider.Meta().(*AWSClient).codedeployconn 376 377 resp, err := conn.GetDeploymentGroup(&codedeploy.GetDeploymentGroupInput{ 378 ApplicationName: aws.String(rs.Primary.Attributes["app_name"]), 379 DeploymentGroupName: aws.String(rs.Primary.Attributes["deployment_group_name"]), 380 }) 381 382 if err != nil { 383 return err 384 } 385 386 *group = *resp.DeploymentGroupInfo 387 388 return nil 389 } 390 } 391 392 var testAccAWSCodeDeployDeploymentGroup = ` 393 resource "aws_codedeploy_app" "foo_app" { 394 name = "foo_app" 395 } 396 397 resource "aws_iam_role_policy" "foo_policy" { 398 name = "foo_policy" 399 role = "${aws_iam_role.foo_role.id}" 400 policy = <<EOF 401 { 402 "Version": "2012-10-17", 403 "Statement": [ 404 { 405 "Effect": "Allow", 406 "Action": [ 407 "autoscaling:CompleteLifecycleAction", 408 "autoscaling:DeleteLifecycleHook", 409 "autoscaling:DescribeAutoScalingGroups", 410 "autoscaling:DescribeLifecycleHooks", 411 "autoscaling:PutLifecycleHook", 412 "autoscaling:RecordLifecycleActionHeartbeat", 413 "ec2:DescribeInstances", 414 "ec2:DescribeInstanceStatus", 415 "tag:GetTags", 416 "tag:GetResources" 417 ], 418 "Resource": "*" 419 } 420 ] 421 } 422 EOF 423 } 424 425 resource "aws_iam_role" "foo_role" { 426 name = "foo_role" 427 assume_role_policy = <<EOF 428 { 429 "Version": "2012-10-17", 430 "Statement": [ 431 { 432 "Sid": "", 433 "Effect": "Allow", 434 "Principal": { 435 "Service": [ 436 "codedeploy.amazonaws.com" 437 ] 438 }, 439 "Action": "sts:AssumeRole" 440 } 441 ] 442 } 443 EOF 444 } 445 446 resource "aws_codedeploy_deployment_group" "foo" { 447 app_name = "${aws_codedeploy_app.foo_app.name}" 448 deployment_group_name = "foo" 449 service_role_arn = "${aws_iam_role.foo_role.arn}" 450 ec2_tag_filter { 451 key = "filterkey" 452 type = "KEY_AND_VALUE" 453 value = "filtervalue" 454 } 455 }` 456 457 var testAccAWSCodeDeployDeploymentGroupModified = ` 458 resource "aws_codedeploy_app" "foo_app" { 459 name = "foo_app" 460 } 461 462 resource "aws_iam_role_policy" "foo_policy" { 463 name = "foo_policy" 464 role = "${aws_iam_role.foo_role.id}" 465 policy = <<EOF 466 { 467 "Version": "2012-10-17", 468 "Statement": [ 469 { 470 "Effect": "Allow", 471 "Action": [ 472 "autoscaling:CompleteLifecycleAction", 473 "autoscaling:DeleteLifecycleHook", 474 "autoscaling:DescribeAutoScalingGroups", 475 "autoscaling:DescribeLifecycleHooks", 476 "autoscaling:PutLifecycleHook", 477 "autoscaling:RecordLifecycleActionHeartbeat", 478 "ec2:DescribeInstances", 479 "ec2:DescribeInstanceStatus", 480 "tag:GetTags", 481 "tag:GetResources" 482 ], 483 "Resource": "*" 484 } 485 ] 486 } 487 EOF 488 } 489 490 resource "aws_iam_role" "foo_role" { 491 name = "foo_role" 492 assume_role_policy = <<EOF 493 { 494 "Version": "2012-10-17", 495 "Statement": [ 496 { 497 "Sid": "", 498 "Effect": "Allow", 499 "Principal": { 500 "Service": [ 501 "codedeploy.amazonaws.com" 502 ] 503 }, 504 "Action": "sts:AssumeRole" 505 } 506 ] 507 } 508 EOF 509 } 510 511 resource "aws_codedeploy_deployment_group" "foo" { 512 app_name = "${aws_codedeploy_app.foo_app.name}" 513 deployment_group_name = "bar" 514 service_role_arn = "${aws_iam_role.foo_role.arn}" 515 ec2_tag_filter { 516 key = "filterkey" 517 type = "KEY_AND_VALUE" 518 value = "anotherfiltervalue" 519 } 520 }` 521 522 const baseCodeDeployConfig = ` 523 resource "aws_codedeploy_app" "foo_app" { 524 name = "foo-app" 525 } 526 527 resource "aws_iam_role_policy" "foo_policy" { 528 name = "foo-policy" 529 role = "${aws_iam_role.foo_role.id}" 530 policy = <<EOF 531 { 532 "Version": "2012-10-17", 533 "Statement": [ 534 { 535 "Effect": "Allow", 536 "Action": [ 537 "autoscaling:CompleteLifecycleAction", 538 "autoscaling:DeleteLifecycleHook", 539 "autoscaling:DescribeAutoScalingGroups", 540 "autoscaling:DescribeLifecycleHooks", 541 "autoscaling:PutLifecycleHook", 542 "autoscaling:RecordLifecycleActionHeartbeat", 543 "ec2:DescribeInstances", 544 "ec2:DescribeInstanceStatus", 545 "tag:GetTags", 546 "tag:GetResources", 547 "sns:Publish" 548 ], 549 "Resource": "*" 550 } 551 ] 552 } 553 EOF 554 } 555 556 resource "aws_iam_role" "foo_role" { 557 name = "foo-role" 558 assume_role_policy = <<EOF 559 { 560 "Version": "2012-10-17", 561 "Statement": [ 562 { 563 "Sid": "", 564 "Effect": "Allow", 565 "Principal": { 566 "Service": "codedeploy.amazonaws.com" 567 }, 568 "Action": "sts:AssumeRole" 569 } 570 ] 571 } 572 EOF 573 } 574 575 resource "aws_sns_topic" "foo_topic" { 576 name = "foo-topic" 577 } 578 579 ` 580 581 const testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_create = baseCodeDeployConfig + ` 582 resource "aws_codedeploy_deployment_group" "foo_group" { 583 app_name = "${aws_codedeploy_app.foo_app.name}" 584 deployment_group_name = "foo-group" 585 service_role_arn = "${aws_iam_role.foo_role.arn}" 586 587 trigger_configuration { 588 trigger_events = ["DeploymentFailure"] 589 trigger_name = "foo-trigger" 590 trigger_target_arn = "${aws_sns_topic.foo_topic.arn}" 591 } 592 }` 593 594 const testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_update = baseCodeDeployConfig + ` 595 resource "aws_codedeploy_deployment_group" "foo_group" { 596 app_name = "${aws_codedeploy_app.foo_app.name}" 597 deployment_group_name = "foo-group" 598 service_role_arn = "${aws_iam_role.foo_role.arn}" 599 600 trigger_configuration { 601 trigger_events = ["DeploymentSuccess", "DeploymentFailure"] 602 trigger_name = "foo-trigger" 603 trigger_target_arn = "${aws_sns_topic.foo_topic.arn}" 604 } 605 }` 606 607 const testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_createMultiple = baseCodeDeployConfig + ` 608 resource "aws_sns_topic" "bar_topic" { 609 name = "bar-topic" 610 } 611 612 resource "aws_codedeploy_deployment_group" "foo_group" { 613 app_name = "${aws_codedeploy_app.foo_app.name}" 614 deployment_group_name = "foo-group" 615 service_role_arn = "${aws_iam_role.foo_role.arn}" 616 617 trigger_configuration { 618 trigger_events = ["DeploymentFailure"] 619 trigger_name = "foo-trigger" 620 trigger_target_arn = "${aws_sns_topic.foo_topic.arn}" 621 } 622 623 trigger_configuration { 624 trigger_events = ["InstanceFailure"] 625 trigger_name = "bar-trigger" 626 trigger_target_arn = "${aws_sns_topic.bar_topic.arn}" 627 } 628 }` 629 630 const testAccAWSCodeDeployDeploymentGroup_triggerConfiguration_updateMultiple = baseCodeDeployConfig + ` 631 resource "aws_sns_topic" "bar_topic" { 632 name = "bar-topic" 633 } 634 635 resource "aws_sns_topic" "baz_topic" { 636 name = "baz-topic" 637 } 638 639 resource "aws_codedeploy_deployment_group" "foo_group" { 640 app_name = "${aws_codedeploy_app.foo_app.name}" 641 deployment_group_name = "foo-group" 642 service_role_arn = "${aws_iam_role.foo_role.arn}" 643 644 trigger_configuration { 645 trigger_events = ["DeploymentStart", "DeploymentSuccess", "DeploymentFailure", "DeploymentStop"] 646 trigger_name = "foo-trigger" 647 trigger_target_arn = "${aws_sns_topic.foo_topic.arn}" 648 } 649 650 trigger_configuration { 651 trigger_events = ["InstanceFailure"] 652 trigger_name = "bar-trigger" 653 trigger_target_arn = "${aws_sns_topic.baz_topic.arn}" 654 } 655 }`