github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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_takeFinalSnapshot(t *testing.T) { 44 var v rds.DBCluster 45 rInt := acctest.RandInt() 46 47 resource.Test(t, resource.TestCase{ 48 PreCheck: func() { testAccPreCheck(t) }, 49 Providers: testAccProviders, 50 CheckDestroy: testAccCheckAWSClusterSnapshot(rInt), 51 Steps: []resource.TestStep{ 52 { 53 Config: testAccAWSClusterConfigWithFinalSnapshot(rInt), 54 Check: resource.ComposeTestCheckFunc( 55 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 56 ), 57 }, 58 }, 59 }) 60 } 61 62 /// This is a regression test to make sure that we always cover the scenario as hightlighted in 63 /// https://github.com/hashicorp/terraform/issues/11568 64 func TestAccAWSRDSCluster_missingUserNameCausesError(t *testing.T) { 65 resource.Test(t, resource.TestCase{ 66 PreCheck: func() { testAccPreCheck(t) }, 67 Providers: testAccProviders, 68 CheckDestroy: testAccCheckAWSClusterDestroy, 69 Steps: []resource.TestStep{ 70 { 71 Config: testAccAWSClusterConfigWithoutUserNameAndPassword(acctest.RandInt()), 72 ExpectError: regexp.MustCompile(`required field is not set`), 73 }, 74 }, 75 }) 76 } 77 78 func TestAccAWSRDSCluster_updateTags(t *testing.T) { 79 var v rds.DBCluster 80 ri := acctest.RandInt() 81 82 resource.Test(t, resource.TestCase{ 83 PreCheck: func() { testAccPreCheck(t) }, 84 Providers: testAccProviders, 85 CheckDestroy: testAccCheckAWSClusterDestroy, 86 Steps: []resource.TestStep{ 87 { 88 Config: testAccAWSClusterConfig(ri), 89 Check: resource.ComposeTestCheckFunc( 90 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 91 resource.TestCheckResourceAttr( 92 "aws_rds_cluster.default", "tags.%", "1"), 93 ), 94 }, 95 { 96 Config: testAccAWSClusterConfigUpdatedTags(ri), 97 Check: resource.ComposeTestCheckFunc( 98 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 99 resource.TestCheckResourceAttr( 100 "aws_rds_cluster.default", "tags.%", "2"), 101 ), 102 }, 103 }, 104 }) 105 } 106 107 func TestAccAWSRDSCluster_kmsKey(t *testing.T) { 108 var v rds.DBCluster 109 keyRegex := regexp.MustCompile("^arn:aws:kms:") 110 111 resource.Test(t, resource.TestCase{ 112 PreCheck: func() { testAccPreCheck(t) }, 113 Providers: testAccProviders, 114 CheckDestroy: testAccCheckAWSClusterDestroy, 115 Steps: []resource.TestStep{ 116 { 117 Config: testAccAWSClusterConfig_kmsKey(acctest.RandInt()), 118 Check: resource.ComposeTestCheckFunc( 119 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 120 resource.TestMatchResourceAttr( 121 "aws_rds_cluster.default", "kms_key_id", keyRegex), 122 ), 123 }, 124 }, 125 }) 126 } 127 128 func TestAccAWSRDSCluster_encrypted(t *testing.T) { 129 var v rds.DBCluster 130 131 resource.Test(t, resource.TestCase{ 132 PreCheck: func() { testAccPreCheck(t) }, 133 Providers: testAccProviders, 134 CheckDestroy: testAccCheckAWSClusterDestroy, 135 Steps: []resource.TestStep{ 136 { 137 Config: testAccAWSClusterConfig_encrypted(acctest.RandInt()), 138 Check: resource.ComposeTestCheckFunc( 139 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 140 resource.TestCheckResourceAttr( 141 "aws_rds_cluster.default", "storage_encrypted", "true"), 142 resource.TestCheckResourceAttr( 143 "aws_rds_cluster.default", "db_cluster_parameter_group_name", "default.aurora5.6"), 144 ), 145 }, 146 }, 147 }) 148 } 149 150 func TestAccAWSRDSCluster_backupsUpdate(t *testing.T) { 151 var v rds.DBCluster 152 153 ri := acctest.RandInt() 154 resource.Test(t, resource.TestCase{ 155 PreCheck: func() { testAccPreCheck(t) }, 156 Providers: testAccProviders, 157 CheckDestroy: testAccCheckAWSClusterDestroy, 158 Steps: []resource.TestStep{ 159 { 160 Config: testAccAWSClusterConfig_backups(ri), 161 Check: resource.ComposeTestCheckFunc( 162 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 163 resource.TestCheckResourceAttr( 164 "aws_rds_cluster.default", "preferred_backup_window", "07:00-09:00"), 165 resource.TestCheckResourceAttr( 166 "aws_rds_cluster.default", "backup_retention_period", "5"), 167 resource.TestCheckResourceAttr( 168 "aws_rds_cluster.default", "preferred_maintenance_window", "tue:04:00-tue:04:30"), 169 ), 170 }, 171 172 resource.TestStep{ 173 Config: testAccAWSClusterConfig_backupsUpdate(ri), 174 Check: resource.ComposeTestCheckFunc( 175 testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), 176 resource.TestCheckResourceAttr( 177 "aws_rds_cluster.default", "preferred_backup_window", "03:00-09:00"), 178 resource.TestCheckResourceAttr( 179 "aws_rds_cluster.default", "backup_retention_period", "10"), 180 resource.TestCheckResourceAttr( 181 "aws_rds_cluster.default", "preferred_maintenance_window", "wed:01:00-wed:01:30"), 182 ), 183 }, 184 }, 185 }) 186 } 187 188 func testAccCheckAWSClusterDestroy(s *terraform.State) error { 189 for _, rs := range s.RootModule().Resources { 190 if rs.Type != "aws_rds_cluster" { 191 continue 192 } 193 194 // Try to find the Group 195 conn := testAccProvider.Meta().(*AWSClient).rdsconn 196 var err error 197 resp, err := conn.DescribeDBClusters( 198 &rds.DescribeDBClustersInput{ 199 DBClusterIdentifier: aws.String(rs.Primary.ID), 200 }) 201 202 if err == nil { 203 if len(resp.DBClusters) != 0 && 204 *resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID { 205 return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID) 206 } 207 } 208 209 // Return nil if the cluster is already destroyed 210 if awsErr, ok := err.(awserr.Error); ok { 211 if awsErr.Code() == "DBClusterNotFoundFault" { 212 return nil 213 } 214 } 215 216 return err 217 } 218 219 return nil 220 } 221 222 func testAccCheckAWSClusterSnapshot(rInt int) resource.TestCheckFunc { 223 return func(s *terraform.State) error { 224 for _, rs := range s.RootModule().Resources { 225 if rs.Type != "aws_rds_cluster" { 226 continue 227 } 228 229 // Try and delete the snapshot before we check for the cluster not found 230 snapshot_identifier := fmt.Sprintf("foobarbaz-test-terraform-final-snapshot-%d", rInt) 231 232 awsClient := testAccProvider.Meta().(*AWSClient) 233 conn := awsClient.rdsconn 234 235 arn, arnErr := buildRDSClusterARN(snapshot_identifier, awsClient.partition, awsClient.accountid, awsClient.region) 236 tagsARN := strings.Replace(arn, ":cluster:", ":snapshot:", 1) 237 if arnErr != nil { 238 return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, arnErr) 239 } 240 241 log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier) 242 _, snapDeleteErr := conn.DeleteDBClusterSnapshot( 243 &rds.DeleteDBClusterSnapshotInput{ 244 DBClusterSnapshotIdentifier: aws.String(snapshot_identifier), 245 }) 246 if snapDeleteErr != nil { 247 return snapDeleteErr 248 } 249 250 // Try to find the Group 251 var err error 252 resp, err := conn.DescribeDBClusters( 253 &rds.DescribeDBClustersInput{ 254 DBClusterIdentifier: aws.String(rs.Primary.ID), 255 }) 256 257 if err == nil { 258 if len(resp.DBClusters) != 0 && 259 *resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID { 260 return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID) 261 } 262 } 263 264 // Return nil if the cluster is already destroyed 265 if awsErr, ok := err.(awserr.Error); ok { 266 if awsErr.Code() == "DBClusterNotFoundFault" { 267 return nil 268 } 269 } 270 271 return err 272 } 273 274 return nil 275 } 276 } 277 278 func testAccCheckAWSClusterExists(n string, v *rds.DBCluster) resource.TestCheckFunc { 279 return func(s *terraform.State) error { 280 rs, ok := s.RootModule().Resources[n] 281 if !ok { 282 return fmt.Errorf("Not found: %s", n) 283 } 284 285 if rs.Primary.ID == "" { 286 return fmt.Errorf("No DB Instance ID is set") 287 } 288 289 conn := testAccProvider.Meta().(*AWSClient).rdsconn 290 resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{ 291 DBClusterIdentifier: aws.String(rs.Primary.ID), 292 }) 293 294 if err != nil { 295 return err 296 } 297 298 for _, c := range resp.DBClusters { 299 if *c.DBClusterIdentifier == rs.Primary.ID { 300 *v = *c 301 return nil 302 } 303 } 304 305 return fmt.Errorf("DB Cluster (%s) not found", rs.Primary.ID) 306 } 307 } 308 309 func testAccAWSClusterConfig(n int) string { 310 return fmt.Sprintf(` 311 resource "aws_rds_cluster" "default" { 312 cluster_identifier = "tf-aurora-cluster-%d" 313 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 314 database_name = "mydb" 315 master_username = "foo" 316 master_password = "mustbeeightcharaters" 317 db_cluster_parameter_group_name = "default.aurora5.6" 318 skip_final_snapshot = true 319 tags { 320 Environment = "production" 321 } 322 }`, n) 323 } 324 325 func testAccAWSClusterConfigWithFinalSnapshot(n int) string { 326 return fmt.Sprintf(` 327 resource "aws_rds_cluster" "default" { 328 cluster_identifier = "tf-aurora-cluster-%d" 329 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 330 database_name = "mydb" 331 master_username = "foo" 332 master_password = "mustbeeightcharaters" 333 db_cluster_parameter_group_name = "default.aurora5.6" 334 skip_final_snapshot = true 335 final_snapshot_identifier = "tf-acctest-rdscluster-snapshot-%d" 336 tags { 337 Environment = "production" 338 } 339 }`, n, n) 340 } 341 342 func testAccAWSClusterConfigWithoutUserNameAndPassword(n int) string { 343 return fmt.Sprintf(` 344 resource "aws_rds_cluster" "default" { 345 cluster_identifier = "tf-aurora-cluster-%d" 346 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 347 database_name = "mydb" 348 skip_final_snapshot = true 349 }`, n) 350 } 351 352 func testAccAWSClusterConfigUpdatedTags(n int) string { 353 return fmt.Sprintf(` 354 resource "aws_rds_cluster" "default" { 355 cluster_identifier = "tf-aurora-cluster-%d" 356 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 357 database_name = "mydb" 358 master_username = "foo" 359 master_password = "mustbeeightcharaters" 360 db_cluster_parameter_group_name = "default.aurora5.6" 361 skip_final_snapshot = true 362 tags { 363 Environment = "production" 364 AnotherTag = "test" 365 } 366 }`, n) 367 } 368 369 func testAccAWSClusterConfig_kmsKey(n int) string { 370 return fmt.Sprintf(` 371 372 resource "aws_kms_key" "foo" { 373 description = "Terraform acc test %d" 374 policy = <<POLICY 375 { 376 "Version": "2012-10-17", 377 "Id": "kms-tf-1", 378 "Statement": [ 379 { 380 "Sid": "Enable IAM User Permissions", 381 "Effect": "Allow", 382 "Principal": { 383 "AWS": "*" 384 }, 385 "Action": "kms:*", 386 "Resource": "*" 387 } 388 ] 389 } 390 POLICY 391 } 392 393 resource "aws_rds_cluster" "default" { 394 cluster_identifier = "tf-aurora-cluster-%d" 395 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 396 database_name = "mydb" 397 master_username = "foo" 398 master_password = "mustbeeightcharaters" 399 db_cluster_parameter_group_name = "default.aurora5.6" 400 storage_encrypted = true 401 kms_key_id = "${aws_kms_key.foo.arn}" 402 skip_final_snapshot = true 403 }`, n, n) 404 } 405 406 func testAccAWSClusterConfig_encrypted(n int) string { 407 return fmt.Sprintf(` 408 resource "aws_rds_cluster" "default" { 409 cluster_identifier = "tf-aurora-cluster-%d" 410 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 411 database_name = "mydb" 412 master_username = "foo" 413 master_password = "mustbeeightcharaters" 414 storage_encrypted = true 415 skip_final_snapshot = true 416 }`, n) 417 } 418 419 func testAccAWSClusterConfig_backups(n int) string { 420 return fmt.Sprintf(` 421 resource "aws_rds_cluster" "default" { 422 cluster_identifier = "tf-aurora-cluster-%d" 423 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 424 database_name = "mydb" 425 master_username = "foo" 426 master_password = "mustbeeightcharaters" 427 backup_retention_period = 5 428 preferred_backup_window = "07:00-09:00" 429 preferred_maintenance_window = "tue:04:00-tue:04:30" 430 skip_final_snapshot = true 431 }`, n) 432 } 433 434 func testAccAWSClusterConfig_backupsUpdate(n int) string { 435 return fmt.Sprintf(` 436 resource "aws_rds_cluster" "default" { 437 cluster_identifier = "tf-aurora-cluster-%d" 438 availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] 439 database_name = "mydb" 440 master_username = "foo" 441 master_password = "mustbeeightcharaters" 442 backup_retention_period = 10 443 preferred_backup_window = "03:00-09:00" 444 preferred_maintenance_window = "wed:01:00-wed:01:30" 445 apply_immediately = true 446 skip_final_snapshot = true 447 }`, n) 448 }