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