github.com/jrperritt/terraform@v0.1.1-0.20170525065507-96f391dafc38/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 tags { 398 Name = "testAccAWSClusterConfig_namePrefix" 399 } 400 } 401 402 resource "aws_subnet" "a" { 403 vpc_id = "${aws_vpc.test.id}" 404 cidr_block = "10.0.0.0/24" 405 availability_zone = "us-west-2a" 406 } 407 408 resource "aws_subnet" "b" { 409 vpc_id = "${aws_vpc.test.id}" 410 cidr_block = "10.0.1.0/24" 411 availability_zone = "us-west-2b" 412 } 413 414 resource "aws_db_subnet_group" "test" { 415 name = "tf-test-%d" 416 subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"] 417 } 418 `, n) 419 } 420 421 func testAccAWSClusterConfig_generatedName(n int) string { 422 return fmt.Sprintf(` 423 resource "aws_rds_cluster" "test" { 424 master_username = "root" 425 master_password = "password" 426 db_subnet_group_name = "${aws_db_subnet_group.test.name}" 427 skip_final_snapshot = true 428 } 429 430 resource "aws_vpc" "test" { 431 cidr_block = "10.0.0.0/16" 432 tags { 433 Name = "testAccAWSClusterConfig_generatedName" 434 } 435 } 436 437 resource "aws_subnet" "a" { 438 vpc_id = "${aws_vpc.test.id}" 439 cidr_block = "10.0.0.0/24" 440 availability_zone = "us-west-2a" 441 } 442 443 resource "aws_subnet" "b" { 444 vpc_id = "${aws_vpc.test.id}" 445 cidr_block = "10.0.1.0/24" 446 availability_zone = "us-west-2b" 447 } 448 449 resource "aws_db_subnet_group" "test" { 450 name = "tf-test-%d" 451 subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"] 452 } 453 `, n) 454 } 455 456 func testAccAWSClusterConfigWithFinalSnapshot(n int) string { 457 return fmt.Sprintf(` 458 resource "aws_rds_cluster" "default" { 459 cluster_identifier = "tf-aurora-cluster-%d" 460 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 461 database_name = "mydb" 462 master_username = "foo" 463 master_password = "mustbeeightcharaters" 464 db_cluster_parameter_group_name = "default.aurora5.6" 465 final_snapshot_identifier = "tf-acctest-rdscluster-snapshot-%d" 466 tags { 467 Environment = "production" 468 } 469 }`, n, n) 470 } 471 472 func testAccAWSClusterConfigWithoutUserNameAndPassword(n int) string { 473 return fmt.Sprintf(` 474 resource "aws_rds_cluster" "default" { 475 cluster_identifier = "tf-aurora-cluster-%d" 476 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 477 database_name = "mydb" 478 skip_final_snapshot = true 479 }`, n) 480 } 481 482 func testAccAWSClusterConfigUpdatedTags(n int) string { 483 return fmt.Sprintf(` 484 resource "aws_rds_cluster" "default" { 485 cluster_identifier = "tf-aurora-cluster-%d" 486 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 487 database_name = "mydb" 488 master_username = "foo" 489 master_password = "mustbeeightcharaters" 490 db_cluster_parameter_group_name = "default.aurora5.6" 491 skip_final_snapshot = true 492 tags { 493 Environment = "production" 494 AnotherTag = "test" 495 } 496 }`, n) 497 } 498 499 func testAccAWSClusterConfig_kmsKey(n int) string { 500 return fmt.Sprintf(` 501 502 resource "aws_kms_key" "foo" { 503 description = "Terraform acc test %d" 504 policy = <<POLICY 505 { 506 "Version": "2012-10-17", 507 "Id": "kms-tf-1", 508 "Statement": [ 509 { 510 "Sid": "Enable IAM User Permissions", 511 "Effect": "Allow", 512 "Principal": { 513 "AWS": "*" 514 }, 515 "Action": "kms:*", 516 "Resource": "*" 517 } 518 ] 519 } 520 POLICY 521 } 522 523 resource "aws_rds_cluster" "default" { 524 cluster_identifier = "tf-aurora-cluster-%d" 525 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 526 database_name = "mydb" 527 master_username = "foo" 528 master_password = "mustbeeightcharaters" 529 db_cluster_parameter_group_name = "default.aurora5.6" 530 storage_encrypted = true 531 kms_key_id = "${aws_kms_key.foo.arn}" 532 skip_final_snapshot = true 533 }`, n, n) 534 } 535 536 func testAccAWSClusterConfig_encrypted(n int) string { 537 return fmt.Sprintf(` 538 resource "aws_rds_cluster" "default" { 539 cluster_identifier = "tf-aurora-cluster-%d" 540 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 541 database_name = "mydb" 542 master_username = "foo" 543 master_password = "mustbeeightcharaters" 544 storage_encrypted = true 545 skip_final_snapshot = true 546 }`, n) 547 } 548 549 func testAccAWSClusterConfig_backups(n int) string { 550 return fmt.Sprintf(` 551 resource "aws_rds_cluster" "default" { 552 cluster_identifier = "tf-aurora-cluster-%d" 553 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 554 database_name = "mydb" 555 master_username = "foo" 556 master_password = "mustbeeightcharaters" 557 backup_retention_period = 5 558 preferred_backup_window = "07:00-09:00" 559 preferred_maintenance_window = "tue:04:00-tue:04:30" 560 skip_final_snapshot = true 561 }`, n) 562 } 563 564 func testAccAWSClusterConfig_backupsUpdate(n int) string { 565 return fmt.Sprintf(` 566 resource "aws_rds_cluster" "default" { 567 cluster_identifier = "tf-aurora-cluster-%d" 568 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 569 database_name = "mydb" 570 master_username = "foo" 571 master_password = "mustbeeightcharaters" 572 backup_retention_period = 10 573 preferred_backup_window = "03:00-09:00" 574 preferred_maintenance_window = "wed:01:00-wed:01:30" 575 apply_immediately = true 576 skip_final_snapshot = true 577 }`, n) 578 } 579 580 func testAccAWSClusterConfig_iamAuth(n int) string { 581 return fmt.Sprintf(` 582 resource "aws_rds_cluster" "default" { 583 cluster_identifier = "tf-aurora-cluster-%d" 584 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 585 database_name = "mydb" 586 master_username = "foo" 587 master_password = "mustbeeightcharaters" 588 iam_database_authentication_enabled = true 589 skip_final_snapshot = true 590 }`, n) 591 }