github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/aws/resource_aws_rds_cluster_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "regexp" 7 "strings" 8 "testing" 9 10 "github.com/hashicorp/terraform/helper/acctest" 11 "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/terraform" 13 14 "github.com/aws/aws-sdk-go/aws" 15 "github.com/aws/aws-sdk-go/aws/awserr" 16 "github.com/aws/aws-sdk-go/service/rds" 17 ) 18 19 func TestAccAWSRDSCluster_basic(t *testing.T) { 20 var v rds.DBCluster 21 22 resource.Test(t, resource.TestCase{ 23 PreCheck: func() { testAccPreCheck(t) }, 24 Providers: testAccProviders, 25 CheckDestroy: testAccCheckAWSClusterDestroy, 26 Steps: []resource.TestStep{ 27 { 28 Config: testAccAWSClusterConfig(acctest.RandInt()), 29 Check: resource.ComposeTestCheckFunc( 30 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 31 resource.TestCheckResourceAttr( 32 "aws_rds_cluster.default", "storage_encrypted", "false"), 33 resource.TestCheckResourceAttr( 34 "aws_rds_cluster.default", "db_cluster_parameter_group_name", "default.aurora5.6"), 35 resource.TestCheckResourceAttrSet( 36 "aws_rds_cluster.default", "reader_endpoint"), 37 resource.TestCheckResourceAttrSet( 38 "aws_rds_cluster.default", "cluster_resource_id"), 39 ), 40 }, 41 }, 42 }) 43 } 44 45 func TestAccAWSRDSCluster_namePrefix(t *testing.T) { 46 var v rds.DBCluster 47 48 resource.Test(t, resource.TestCase{ 49 PreCheck: func() { testAccPreCheck(t) }, 50 Providers: testAccProviders, 51 CheckDestroy: testAccCheckAWSClusterDestroy, 52 Steps: []resource.TestStep{ 53 { 54 Config: testAccAWSClusterConfig_namePrefix(acctest.RandInt()), 55 Check: resource.ComposeTestCheckFunc( 56 testAccCheckAWSClusterExists("aws_rds_cluster.test", &v), 57 resource.TestMatchResourceAttr( 58 "aws_rds_cluster.test", "cluster_identifier", regexp.MustCompile("^tf-test-")), 59 ), 60 }, 61 }, 62 }) 63 } 64 65 func TestAccAWSRDSCluster_generatedName(t *testing.T) { 66 var v rds.DBCluster 67 68 resource.Test(t, resource.TestCase{ 69 PreCheck: func() { testAccPreCheck(t) }, 70 Providers: testAccProviders, 71 CheckDestroy: testAccCheckAWSClusterDestroy, 72 Steps: []resource.TestStep{ 73 { 74 Config: testAccAWSClusterConfig_generatedName(acctest.RandInt()), 75 Check: resource.ComposeTestCheckFunc( 76 testAccCheckAWSClusterExists("aws_rds_cluster.test", &v), 77 resource.TestMatchResourceAttr( 78 "aws_rds_cluster.test", "cluster_identifier", regexp.MustCompile("^tf-")), 79 ), 80 }, 81 }, 82 }) 83 } 84 85 func TestAccAWSRDSCluster_takeFinalSnapshot(t *testing.T) { 86 var v rds.DBCluster 87 rInt := acctest.RandInt() 88 89 resource.Test(t, resource.TestCase{ 90 PreCheck: func() { testAccPreCheck(t) }, 91 Providers: testAccProviders, 92 CheckDestroy: testAccCheckAWSClusterSnapshot(rInt), 93 Steps: []resource.TestStep{ 94 { 95 Config: testAccAWSClusterConfigWithFinalSnapshot(rInt), 96 Check: resource.ComposeTestCheckFunc( 97 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 98 ), 99 }, 100 }, 101 }) 102 } 103 104 /// This is a regression test to make sure that we always cover the scenario as hightlighted in 105 /// https://github.com/hashicorp/terraform/issues/11568 106 func TestAccAWSRDSCluster_missingUserNameCausesError(t *testing.T) { 107 resource.Test(t, resource.TestCase{ 108 PreCheck: func() { testAccPreCheck(t) }, 109 Providers: testAccProviders, 110 CheckDestroy: testAccCheckAWSClusterDestroy, 111 Steps: []resource.TestStep{ 112 { 113 Config: testAccAWSClusterConfigWithoutUserNameAndPassword(acctest.RandInt()), 114 ExpectError: regexp.MustCompile(`required field is not set`), 115 }, 116 }, 117 }) 118 } 119 120 func TestAccAWSRDSCluster_updateTags(t *testing.T) { 121 var v rds.DBCluster 122 ri := acctest.RandInt() 123 124 resource.Test(t, resource.TestCase{ 125 PreCheck: func() { testAccPreCheck(t) }, 126 Providers: testAccProviders, 127 CheckDestroy: testAccCheckAWSClusterDestroy, 128 Steps: []resource.TestStep{ 129 { 130 Config: testAccAWSClusterConfig(ri), 131 Check: resource.ComposeTestCheckFunc( 132 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 133 resource.TestCheckResourceAttr( 134 "aws_rds_cluster.default", "tags.%", "1"), 135 ), 136 }, 137 { 138 Config: testAccAWSClusterConfigUpdatedTags(ri), 139 Check: resource.ComposeTestCheckFunc( 140 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 141 resource.TestCheckResourceAttr( 142 "aws_rds_cluster.default", "tags.%", "2"), 143 ), 144 }, 145 }, 146 }) 147 } 148 149 func TestAccAWSRDSCluster_kmsKey(t *testing.T) { 150 var v rds.DBCluster 151 keyRegex := regexp.MustCompile("^arn:aws:kms:") 152 153 resource.Test(t, resource.TestCase{ 154 PreCheck: func() { testAccPreCheck(t) }, 155 Providers: testAccProviders, 156 CheckDestroy: testAccCheckAWSClusterDestroy, 157 Steps: []resource.TestStep{ 158 { 159 Config: testAccAWSClusterConfig_kmsKey(acctest.RandInt()), 160 Check: resource.ComposeTestCheckFunc( 161 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 162 resource.TestMatchResourceAttr( 163 "aws_rds_cluster.default", "kms_key_id", keyRegex), 164 ), 165 }, 166 }, 167 }) 168 } 169 170 func TestAccAWSRDSCluster_encrypted(t *testing.T) { 171 var v rds.DBCluster 172 173 resource.Test(t, resource.TestCase{ 174 PreCheck: func() { testAccPreCheck(t) }, 175 Providers: testAccProviders, 176 CheckDestroy: testAccCheckAWSClusterDestroy, 177 Steps: []resource.TestStep{ 178 { 179 Config: testAccAWSClusterConfig_encrypted(acctest.RandInt()), 180 Check: resource.ComposeTestCheckFunc( 181 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 182 resource.TestCheckResourceAttr( 183 "aws_rds_cluster.default", "storage_encrypted", "true"), 184 resource.TestCheckResourceAttr( 185 "aws_rds_cluster.default", "db_cluster_parameter_group_name", "default.aurora5.6"), 186 ), 187 }, 188 }, 189 }) 190 } 191 192 func TestAccAWSRDSCluster_backupsUpdate(t *testing.T) { 193 var v rds.DBCluster 194 195 ri := acctest.RandInt() 196 resource.Test(t, resource.TestCase{ 197 PreCheck: func() { testAccPreCheck(t) }, 198 Providers: testAccProviders, 199 CheckDestroy: testAccCheckAWSClusterDestroy, 200 Steps: []resource.TestStep{ 201 { 202 Config: testAccAWSClusterConfig_backups(ri), 203 Check: resource.ComposeTestCheckFunc( 204 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 205 resource.TestCheckResourceAttr( 206 "aws_rds_cluster.default", "preferred_backup_window", "07:00-09:00"), 207 resource.TestCheckResourceAttr( 208 "aws_rds_cluster.default", "backup_retention_period", "5"), 209 resource.TestCheckResourceAttr( 210 "aws_rds_cluster.default", "preferred_maintenance_window", "tue:04:00-tue:04:30"), 211 ), 212 }, 213 214 resource.TestStep{ 215 Config: testAccAWSClusterConfig_backupsUpdate(ri), 216 Check: resource.ComposeTestCheckFunc( 217 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 218 resource.TestCheckResourceAttr( 219 "aws_rds_cluster.default", "preferred_backup_window", "03:00-09:00"), 220 resource.TestCheckResourceAttr( 221 "aws_rds_cluster.default", "backup_retention_period", "10"), 222 resource.TestCheckResourceAttr( 223 "aws_rds_cluster.default", "preferred_maintenance_window", "wed:01:00-wed:01:30"), 224 ), 225 }, 226 }, 227 }) 228 } 229 230 func TestAccAWSRDSCluster_iamAuth(t *testing.T) { 231 var v rds.DBCluster 232 233 resource.Test(t, resource.TestCase{ 234 PreCheck: func() { testAccPreCheck(t) }, 235 Providers: testAccProviders, 236 CheckDestroy: testAccCheckAWSClusterDestroy, 237 Steps: []resource.TestStep{ 238 { 239 Config: testAccAWSClusterConfig_iamAuth(acctest.RandInt()), 240 Check: resource.ComposeTestCheckFunc( 241 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 242 resource.TestCheckResourceAttr( 243 "aws_rds_cluster.default", "iam_database_authentication_enabled", "true"), 244 ), 245 }, 246 }, 247 }) 248 } 249 250 func testAccCheckAWSClusterDestroy(s *terraform.State) error { 251 for _, rs := range s.RootModule().Resources { 252 if rs.Type != "aws_rds_cluster" { 253 continue 254 } 255 256 // Try to find the Group 257 conn := testAccProvider.Meta().(*AWSClient).rdsconn 258 var err error 259 resp, err := conn.DescribeDBClusters( 260 &rds.DescribeDBClustersInput{ 261 DBClusterIdentifier: aws.String(rs.Primary.ID), 262 }) 263 264 if err == nil { 265 if len(resp.DBClusters) != 0 && 266 *resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID { 267 return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID) 268 } 269 } 270 271 // Return nil if the cluster is already destroyed 272 if awsErr, ok := err.(awserr.Error); ok { 273 if awsErr.Code() == "DBClusterNotFoundFault" { 274 return nil 275 } 276 } 277 278 return err 279 } 280 281 return nil 282 } 283 284 func testAccCheckAWSClusterSnapshot(rInt int) resource.TestCheckFunc { 285 return func(s *terraform.State) error { 286 for _, rs := range s.RootModule().Resources { 287 if rs.Type != "aws_rds_cluster" { 288 continue 289 } 290 291 // Try and delete the snapshot before we check for the cluster not found 292 snapshot_identifier := fmt.Sprintf("tf-acctest-rdscluster-snapshot-%d", rInt) 293 294 awsClient := testAccProvider.Meta().(*AWSClient) 295 conn := awsClient.rdsconn 296 297 arn, arnErr := buildRDSClusterARN(snapshot_identifier, awsClient.partition, awsClient.accountid, awsClient.region) 298 tagsARN := strings.Replace(arn, ":cluster:", ":snapshot:", 1) 299 if arnErr != nil { 300 return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, arnErr) 301 } 302 303 log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier) 304 _, snapDeleteErr := conn.DeleteDBClusterSnapshot( 305 &rds.DeleteDBClusterSnapshotInput{ 306 DBClusterSnapshotIdentifier: aws.String(snapshot_identifier), 307 }) 308 if snapDeleteErr != nil { 309 return snapDeleteErr 310 } 311 312 // Try to find the Group 313 var err error 314 resp, err := conn.DescribeDBClusters( 315 &rds.DescribeDBClustersInput{ 316 DBClusterIdentifier: aws.String(rs.Primary.ID), 317 }) 318 319 if err == nil { 320 if len(resp.DBClusters) != 0 && 321 *resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID { 322 return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID) 323 } 324 } 325 326 // Return nil if the cluster is already destroyed 327 if awsErr, ok := err.(awserr.Error); ok { 328 if awsErr.Code() == "DBClusterNotFoundFault" { 329 return nil 330 } 331 } 332 333 return err 334 } 335 336 return nil 337 } 338 } 339 340 func testAccCheckAWSClusterExists(n string, v *rds.DBCluster) resource.TestCheckFunc { 341 return func(s *terraform.State) error { 342 rs, ok := s.RootModule().Resources[n] 343 if !ok { 344 return fmt.Errorf("Not found: %s", n) 345 } 346 347 if rs.Primary.ID == "" { 348 return fmt.Errorf("No DB Instance ID is set") 349 } 350 351 conn := testAccProvider.Meta().(*AWSClient).rdsconn 352 resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{ 353 DBClusterIdentifier: aws.String(rs.Primary.ID), 354 }) 355 356 if err != nil { 357 return err 358 } 359 360 for _, c := range resp.DBClusters { 361 if *c.DBClusterIdentifier == rs.Primary.ID { 362 *v = *c 363 return nil 364 } 365 } 366 367 return fmt.Errorf("DB Cluster (%s) not found", rs.Primary.ID) 368 } 369 } 370 371 func testAccAWSClusterConfig(n int) string { 372 return fmt.Sprintf(` 373 resource "aws_rds_cluster" "default" { 374 cluster_identifier = "tf-aurora-cluster-%d" 375 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 376 database_name = "mydb" 377 master_username = "foo" 378 master_password = "mustbeeightcharaters" 379 db_cluster_parameter_group_name = "default.aurora5.6" 380 skip_final_snapshot = true 381 tags { 382 Environment = "production" 383 } 384 }`, n) 385 } 386 387 func testAccAWSClusterConfig_namePrefix(n int) string { 388 return fmt.Sprintf(` 389 resource "aws_rds_cluster" "test" { 390 cluster_identifier_prefix = "tf-test-" 391 master_username = "root" 392 master_password = "password" 393 db_subnet_group_name = "${aws_db_subnet_group.test.name}" 394 skip_final_snapshot = true 395 } 396 397 resource "aws_vpc" "test" { 398 cidr_block = "10.0.0.0/16" 399 tags { 400 Name = "testAccAWSClusterConfig_namePrefix" 401 } 402 } 403 404 resource "aws_subnet" "a" { 405 vpc_id = "${aws_vpc.test.id}" 406 cidr_block = "10.0.0.0/24" 407 availability_zone = "us-west-2a" 408 } 409 410 resource "aws_subnet" "b" { 411 vpc_id = "${aws_vpc.test.id}" 412 cidr_block = "10.0.1.0/24" 413 availability_zone = "us-west-2b" 414 } 415 416 resource "aws_db_subnet_group" "test" { 417 name = "tf-test-%d" 418 subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"] 419 } 420 `, n) 421 } 422 423 func testAccAWSClusterConfig_generatedName(n int) string { 424 return fmt.Sprintf(` 425 resource "aws_rds_cluster" "test" { 426 master_username = "root" 427 master_password = "password" 428 db_subnet_group_name = "${aws_db_subnet_group.test.name}" 429 skip_final_snapshot = true 430 } 431 432 resource "aws_vpc" "test" { 433 cidr_block = "10.0.0.0/16" 434 tags { 435 Name = "testAccAWSClusterConfig_generatedName" 436 } 437 } 438 439 resource "aws_subnet" "a" { 440 vpc_id = "${aws_vpc.test.id}" 441 cidr_block = "10.0.0.0/24" 442 availability_zone = "us-west-2a" 443 } 444 445 resource "aws_subnet" "b" { 446 vpc_id = "${aws_vpc.test.id}" 447 cidr_block = "10.0.1.0/24" 448 availability_zone = "us-west-2b" 449 } 450 451 resource "aws_db_subnet_group" "test" { 452 name = "tf-test-%d" 453 subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"] 454 } 455 `, n) 456 } 457 458 func testAccAWSClusterConfigWithFinalSnapshot(n int) string { 459 return fmt.Sprintf(` 460 resource "aws_rds_cluster" "default" { 461 cluster_identifier = "tf-aurora-cluster-%d" 462 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 463 database_name = "mydb" 464 master_username = "foo" 465 master_password = "mustbeeightcharaters" 466 db_cluster_parameter_group_name = "default.aurora5.6" 467 final_snapshot_identifier = "tf-acctest-rdscluster-snapshot-%d" 468 tags { 469 Environment = "production" 470 } 471 }`, n, n) 472 } 473 474 func testAccAWSClusterConfigWithoutUserNameAndPassword(n int) string { 475 return fmt.Sprintf(` 476 resource "aws_rds_cluster" "default" { 477 cluster_identifier = "tf-aurora-cluster-%d" 478 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 479 database_name = "mydb" 480 skip_final_snapshot = true 481 }`, n) 482 } 483 484 func testAccAWSClusterConfigUpdatedTags(n int) string { 485 return fmt.Sprintf(` 486 resource "aws_rds_cluster" "default" { 487 cluster_identifier = "tf-aurora-cluster-%d" 488 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 489 database_name = "mydb" 490 master_username = "foo" 491 master_password = "mustbeeightcharaters" 492 db_cluster_parameter_group_name = "default.aurora5.6" 493 skip_final_snapshot = true 494 tags { 495 Environment = "production" 496 AnotherTag = "test" 497 } 498 }`, n) 499 } 500 501 func testAccAWSClusterConfig_kmsKey(n int) string { 502 return fmt.Sprintf(` 503 504 resource "aws_kms_key" "foo" { 505 description = "Terraform acc test %d" 506 policy = <<POLICY 507 { 508 "Version": "2012-10-17", 509 "Id": "kms-tf-1", 510 "Statement": [ 511 { 512 "Sid": "Enable IAM User Permissions", 513 "Effect": "Allow", 514 "Principal": { 515 "AWS": "*" 516 }, 517 "Action": "kms:*", 518 "Resource": "*" 519 } 520 ] 521 } 522 POLICY 523 } 524 525 resource "aws_rds_cluster" "default" { 526 cluster_identifier = "tf-aurora-cluster-%d" 527 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 528 database_name = "mydb" 529 master_username = "foo" 530 master_password = "mustbeeightcharaters" 531 db_cluster_parameter_group_name = "default.aurora5.6" 532 storage_encrypted = true 533 kms_key_id = "${aws_kms_key.foo.arn}" 534 skip_final_snapshot = true 535 }`, n, n) 536 } 537 538 func testAccAWSClusterConfig_encrypted(n int) string { 539 return fmt.Sprintf(` 540 resource "aws_rds_cluster" "default" { 541 cluster_identifier = "tf-aurora-cluster-%d" 542 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 543 database_name = "mydb" 544 master_username = "foo" 545 master_password = "mustbeeightcharaters" 546 storage_encrypted = true 547 skip_final_snapshot = true 548 }`, n) 549 } 550 551 func testAccAWSClusterConfig_backups(n int) string { 552 return fmt.Sprintf(` 553 resource "aws_rds_cluster" "default" { 554 cluster_identifier = "tf-aurora-cluster-%d" 555 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 556 database_name = "mydb" 557 master_username = "foo" 558 master_password = "mustbeeightcharaters" 559 backup_retention_period = 5 560 preferred_backup_window = "07:00-09:00" 561 preferred_maintenance_window = "tue:04:00-tue:04:30" 562 skip_final_snapshot = true 563 }`, n) 564 } 565 566 func testAccAWSClusterConfig_backupsUpdate(n int) string { 567 return fmt.Sprintf(` 568 resource "aws_rds_cluster" "default" { 569 cluster_identifier = "tf-aurora-cluster-%d" 570 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 571 database_name = "mydb" 572 master_username = "foo" 573 master_password = "mustbeeightcharaters" 574 backup_retention_period = 10 575 preferred_backup_window = "03:00-09:00" 576 preferred_maintenance_window = "wed:01:00-wed:01:30" 577 apply_immediately = true 578 skip_final_snapshot = true 579 }`, n) 580 } 581 582 func testAccAWSClusterConfig_iamAuth(n int) string { 583 return fmt.Sprintf(` 584 resource "aws_rds_cluster" "default" { 585 cluster_identifier = "tf-aurora-cluster-%d" 586 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 587 database_name = "mydb" 588 master_username = "foo" 589 master_password = "mustbeeightcharaters" 590 iam_database_authentication_enabled = true 591 skip_final_snapshot = true 592 }`, n) 593 }