github.com/jdextraze/terraform@v0.6.17-0.20160511153921-e33847c8a8af/builtin/providers/aws/resource_aws_db_instance_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "math/rand" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/terraform/helper/acctest" 13 "github.com/hashicorp/terraform/helper/resource" 14 "github.com/hashicorp/terraform/terraform" 15 16 "github.com/aws/aws-sdk-go/aws" 17 "github.com/aws/aws-sdk-go/aws/awserr" 18 "github.com/aws/aws-sdk-go/service/rds" 19 ) 20 21 func TestAccAWSDBInstance_basic(t *testing.T) { 22 var v rds.DBInstance 23 24 resource.Test(t, resource.TestCase{ 25 PreCheck: func() { testAccPreCheck(t) }, 26 Providers: testAccProviders, 27 CheckDestroy: testAccCheckAWSDBInstanceDestroy, 28 Steps: []resource.TestStep{ 29 resource.TestStep{ 30 Config: testAccAWSDBInstanceConfig, 31 Check: resource.ComposeTestCheckFunc( 32 testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v), 33 testAccCheckAWSDBInstanceAttributes(&v), 34 resource.TestCheckResourceAttr( 35 "aws_db_instance.bar", "allocated_storage", "10"), 36 resource.TestCheckResourceAttr( 37 "aws_db_instance.bar", "engine", "mysql"), 38 resource.TestCheckResourceAttr( 39 "aws_db_instance.bar", "license_model", "general-public-license"), 40 resource.TestCheckResourceAttr( 41 "aws_db_instance.bar", "instance_class", "db.t1.micro"), 42 resource.TestCheckResourceAttr( 43 "aws_db_instance.bar", "name", "baz"), 44 resource.TestCheckResourceAttr( 45 "aws_db_instance.bar", "username", "foo"), 46 resource.TestCheckResourceAttr( 47 "aws_db_instance.bar", "parameter_group_name", "default.mysql5.6"), 48 ), 49 }, 50 }, 51 }) 52 } 53 54 func TestAccAWSDBInstance_optionGroup(t *testing.T) { 55 var v rds.DBInstance 56 57 resource.Test(t, resource.TestCase{ 58 PreCheck: func() { testAccPreCheck(t) }, 59 Providers: testAccProviders, 60 CheckDestroy: testAccCheckAWSDBInstanceDestroy, 61 Steps: []resource.TestStep{ 62 resource.TestStep{ 63 Config: testAccAWSDBInstanceConfigWithOptionGroup, 64 Check: resource.ComposeTestCheckFunc( 65 testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v), 66 testAccCheckAWSDBInstanceAttributes(&v), 67 resource.TestCheckResourceAttr( 68 "aws_db_instance.bar", "option_group_name", "option-group-test-terraform"), 69 ), 70 }, 71 }, 72 }) 73 } 74 75 func TestAccAWSDBInstanceReplica(t *testing.T) { 76 var s, r rds.DBInstance 77 78 resource.Test(t, resource.TestCase{ 79 PreCheck: func() { testAccPreCheck(t) }, 80 Providers: testAccProviders, 81 CheckDestroy: testAccCheckAWSDBInstanceDestroy, 82 Steps: []resource.TestStep{ 83 resource.TestStep{ 84 Config: testAccReplicaInstanceConfig(rand.New(rand.NewSource(time.Now().UnixNano())).Int()), 85 Check: resource.ComposeTestCheckFunc( 86 testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &s), 87 testAccCheckAWSDBInstanceExists("aws_db_instance.replica", &r), 88 testAccCheckAWSDBInstanceReplicaAttributes(&s, &r), 89 ), 90 }, 91 }, 92 }) 93 } 94 95 func TestAccAWSDBInstanceSnapshot(t *testing.T) { 96 var snap rds.DBInstance 97 98 resource.Test(t, resource.TestCase{ 99 PreCheck: func() { testAccPreCheck(t) }, 100 Providers: testAccProviders, 101 // testAccCheckAWSDBInstanceSnapshot verifies a database snapshot is 102 // created, and subequently deletes it 103 CheckDestroy: testAccCheckAWSDBInstanceSnapshot, 104 Steps: []resource.TestStep{ 105 resource.TestStep{ 106 Config: testAccSnapshotInstanceConfig(), 107 Check: resource.ComposeTestCheckFunc( 108 testAccCheckAWSDBInstanceExists("aws_db_instance.snapshot", &snap), 109 ), 110 }, 111 }, 112 }) 113 } 114 115 func TestAccAWSDBInstanceNoSnapshot(t *testing.T) { 116 var nosnap rds.DBInstance 117 118 resource.Test(t, resource.TestCase{ 119 PreCheck: func() { testAccPreCheck(t) }, 120 Providers: testAccProviders, 121 CheckDestroy: testAccCheckAWSDBInstanceNoSnapshot, 122 Steps: []resource.TestStep{ 123 resource.TestStep{ 124 Config: testAccNoSnapshotInstanceConfig(), 125 Check: resource.ComposeTestCheckFunc( 126 testAccCheckAWSDBInstanceExists("aws_db_instance.no_snapshot", &nosnap), 127 ), 128 }, 129 }, 130 }) 131 } 132 133 func TestAccAWSDBInstance_enhancedMonitoring(t *testing.T) { 134 var dbInstance rds.DBInstance 135 136 resource.Test(t, resource.TestCase{ 137 PreCheck: func() { testAccPreCheck(t) }, 138 Providers: testAccProviders, 139 CheckDestroy: testAccCheckAWSDBInstanceNoSnapshot, 140 Steps: []resource.TestStep{ 141 resource.TestStep{ 142 Config: testAccSnapshotInstanceConfig_enhancedMonitoring, 143 Check: resource.ComposeTestCheckFunc( 144 testAccCheckAWSDBInstanceExists("aws_db_instance.enhanced_monitoring", &dbInstance), 145 resource.TestCheckResourceAttr( 146 "aws_db_instance.enhanced_monitoring", "monitoring_interval", "5"), 147 ), 148 }, 149 }, 150 }) 151 } 152 153 func testAccCheckAWSDBInstanceDestroy(s *terraform.State) error { 154 conn := testAccProvider.Meta().(*AWSClient).rdsconn 155 156 for _, rs := range s.RootModule().Resources { 157 if rs.Type != "aws_db_instance" { 158 continue 159 } 160 161 // Try to find the Group 162 var err error 163 resp, err := conn.DescribeDBInstances( 164 &rds.DescribeDBInstancesInput{ 165 DBInstanceIdentifier: aws.String(rs.Primary.ID), 166 }) 167 168 if ae, ok := err.(awserr.Error); ok && ae.Code() == "DBInstanceNotFound" { 169 continue 170 } 171 172 if err == nil { 173 if len(resp.DBInstances) != 0 && 174 *resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID { 175 return fmt.Errorf("DB Instance still exists") 176 } 177 } 178 179 // Verify the error 180 newerr, ok := err.(awserr.Error) 181 if !ok { 182 return err 183 } 184 if newerr.Code() != "DBInstanceNotFound" { 185 return err 186 } 187 } 188 189 return nil 190 } 191 192 func testAccCheckAWSDBInstanceAttributes(v *rds.DBInstance) resource.TestCheckFunc { 193 return func(s *terraform.State) error { 194 195 if *v.Engine != "mysql" { 196 return fmt.Errorf("bad engine: %#v", *v.Engine) 197 } 198 199 if *v.EngineVersion == "" { 200 return fmt.Errorf("bad engine_version: %#v", *v.EngineVersion) 201 } 202 203 if *v.BackupRetentionPeriod != 0 { 204 return fmt.Errorf("bad backup_retention_period: %#v", *v.BackupRetentionPeriod) 205 } 206 207 return nil 208 } 209 } 210 211 func testAccCheckAWSDBInstanceReplicaAttributes(source, replica *rds.DBInstance) resource.TestCheckFunc { 212 return func(s *terraform.State) error { 213 214 if replica.ReadReplicaSourceDBInstanceIdentifier != nil && *replica.ReadReplicaSourceDBInstanceIdentifier != *source.DBInstanceIdentifier { 215 return fmt.Errorf("bad source identifier for replica, expected: '%s', got: '%s'", *source.DBInstanceIdentifier, *replica.ReadReplicaSourceDBInstanceIdentifier) 216 } 217 218 return nil 219 } 220 } 221 222 func testAccCheckAWSDBInstanceSnapshot(s *terraform.State) error { 223 conn := testAccProvider.Meta().(*AWSClient).rdsconn 224 225 for _, rs := range s.RootModule().Resources { 226 if rs.Type != "aws_db_instance" { 227 continue 228 } 229 230 var err error 231 resp, err := conn.DescribeDBInstances( 232 &rds.DescribeDBInstancesInput{ 233 DBInstanceIdentifier: aws.String(rs.Primary.ID), 234 }) 235 236 if err != nil { 237 newerr, _ := err.(awserr.Error) 238 if newerr.Code() != "DBInstanceNotFound" { 239 return err 240 } 241 242 } else { 243 if len(resp.DBInstances) != 0 && 244 *resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID { 245 return fmt.Errorf("DB Instance still exists") 246 } 247 } 248 249 log.Printf("[INFO] Trying to locate the DBInstance Final Snapshot") 250 snapshot_identifier := "foobarbaz-test-terraform-final-snapshot-1" 251 _, snapErr := conn.DescribeDBSnapshots( 252 &rds.DescribeDBSnapshotsInput{ 253 DBSnapshotIdentifier: aws.String(snapshot_identifier), 254 }) 255 256 if snapErr != nil { 257 newerr, _ := snapErr.(awserr.Error) 258 if newerr.Code() == "DBSnapshotNotFound" { 259 return fmt.Errorf("Snapshot %s not found", snapshot_identifier) 260 } 261 } else { // snapshot was found 262 // verify we have the tags copied to the snapshot 263 instanceARN, err := buildRDSARN(snapshot_identifier, testAccProvider.Meta()) 264 // tags have a different ARN, just swapping :db: for :snapshot: 265 tagsARN := strings.Replace(instanceARN, ":db:", ":snapshot:", 1) 266 if err != nil { 267 return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, err) 268 } 269 resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{ 270 ResourceName: aws.String(tagsARN), 271 }) 272 if err != nil { 273 return fmt.Errorf("Error retrieving tags for ARN (%s): %s", tagsARN, err) 274 } 275 276 if resp.TagList == nil || len(resp.TagList) == 0 { 277 return fmt.Errorf("Tag list is nil or zero: %s", resp.TagList) 278 } 279 280 var found bool 281 for _, t := range resp.TagList { 282 if *t.Key == "Name" && *t.Value == "tf-tags-db" { 283 found = true 284 } 285 } 286 if !found { 287 return fmt.Errorf("Expected to find tag Name (%s), but wasn't found. Tags: %s", "tf-tags-db", resp.TagList) 288 } 289 // end tag search 290 291 log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier) 292 _, snapDeleteErr := conn.DeleteDBSnapshot( 293 &rds.DeleteDBSnapshotInput{ 294 DBSnapshotIdentifier: aws.String(snapshot_identifier), 295 }) 296 if snapDeleteErr != nil { 297 return err 298 } 299 } // end snapshot was found 300 } 301 302 return nil 303 } 304 305 func testAccCheckAWSDBInstanceNoSnapshot(s *terraform.State) error { 306 conn := testAccProvider.Meta().(*AWSClient).rdsconn 307 308 for _, rs := range s.RootModule().Resources { 309 if rs.Type != "aws_db_instance" { 310 continue 311 } 312 313 var err error 314 resp, err := conn.DescribeDBInstances( 315 &rds.DescribeDBInstancesInput{ 316 DBInstanceIdentifier: aws.String(rs.Primary.ID), 317 }) 318 319 if err != nil { 320 newerr, _ := err.(awserr.Error) 321 if newerr.Code() != "DBInstanceNotFound" { 322 return err 323 } 324 325 } else { 326 if len(resp.DBInstances) != 0 && 327 *resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID { 328 return fmt.Errorf("DB Instance still exists") 329 } 330 } 331 332 snapshot_identifier := "foobarbaz-test-terraform-final-snapshot-2" 333 _, snapErr := conn.DescribeDBSnapshots( 334 &rds.DescribeDBSnapshotsInput{ 335 DBSnapshotIdentifier: aws.String(snapshot_identifier), 336 }) 337 338 if snapErr != nil { 339 newerr, _ := snapErr.(awserr.Error) 340 if newerr.Code() != "DBSnapshotNotFound" { 341 return fmt.Errorf("Snapshot %s found and it shouldn't have been", snapshot_identifier) 342 } 343 } 344 } 345 346 return nil 347 } 348 349 func testAccCheckAWSDBInstanceExists(n string, v *rds.DBInstance) resource.TestCheckFunc { 350 return func(s *terraform.State) error { 351 rs, ok := s.RootModule().Resources[n] 352 if !ok { 353 return fmt.Errorf("Not found: %s", n) 354 } 355 356 if rs.Primary.ID == "" { 357 return fmt.Errorf("No DB Instance ID is set") 358 } 359 360 conn := testAccProvider.Meta().(*AWSClient).rdsconn 361 362 opts := rds.DescribeDBInstancesInput{ 363 DBInstanceIdentifier: aws.String(rs.Primary.ID), 364 } 365 366 resp, err := conn.DescribeDBInstances(&opts) 367 368 if err != nil { 369 return err 370 } 371 372 if len(resp.DBInstances) != 1 || 373 *resp.DBInstances[0].DBInstanceIdentifier != rs.Primary.ID { 374 return fmt.Errorf("DB Instance not found") 375 } 376 377 *v = *resp.DBInstances[0] 378 379 return nil 380 } 381 } 382 383 // Database names cannot collide, and deletion takes so long, that making the 384 // name a bit random helps so able we can kill a test that's just waiting for a 385 // delete and not be blocked on kicking off another one. 386 var testAccAWSDBInstanceConfig = ` 387 resource "aws_db_instance" "bar" { 388 allocated_storage = 10 389 engine = "MySQL" 390 engine_version = "5.6.21" 391 instance_class = "db.t1.micro" 392 name = "baz" 393 password = "barbarbarbar" 394 username = "foo" 395 396 397 # Maintenance Window is stored in lower case in the API, though not strictly 398 # documented. Terraform will downcase this to match (as opposed to throw a 399 # validation error). 400 maintenance_window = "Fri:09:00-Fri:09:30" 401 402 backup_retention_period = 0 403 404 parameter_group_name = "default.mysql5.6" 405 }` 406 407 var testAccAWSDBInstanceConfigWithOptionGroup = fmt.Sprintf(` 408 409 resource "aws_db_option_group" "bar" { 410 name = "option-group-test-terraform" 411 option_group_description = "Test option group for terraform" 412 engine_name = "mysql" 413 major_engine_version = "5.6" 414 } 415 416 resource "aws_db_instance" "bar" { 417 identifier = "foobarbaz-test-terraform-%d" 418 419 allocated_storage = 10 420 engine = "MySQL" 421 instance_class = "db.m1.small" 422 name = "baz" 423 password = "barbarbarbar" 424 username = "foo" 425 426 backup_retention_period = 0 427 428 parameter_group_name = "default.mysql5.6" 429 option_group_name = "${aws_db_option_group.bar.name}" 430 }`, acctest.RandInt()) 431 432 func testAccReplicaInstanceConfig(val int) string { 433 return fmt.Sprintf(` 434 resource "aws_db_instance" "bar" { 435 identifier = "foobarbaz-test-terraform-%d" 436 437 allocated_storage = 5 438 engine = "mysql" 439 engine_version = "5.6.21" 440 instance_class = "db.t1.micro" 441 name = "baz" 442 password = "barbarbarbar" 443 username = "foo" 444 445 backup_retention_period = 1 446 447 parameter_group_name = "default.mysql5.6" 448 } 449 450 resource "aws_db_instance" "replica" { 451 identifier = "tf-replica-db-%d" 452 backup_retention_period = 0 453 replicate_source_db = "${aws_db_instance.bar.identifier}" 454 allocated_storage = "${aws_db_instance.bar.allocated_storage}" 455 engine = "${aws_db_instance.bar.engine}" 456 engine_version = "${aws_db_instance.bar.engine_version}" 457 instance_class = "${aws_db_instance.bar.instance_class}" 458 password = "${aws_db_instance.bar.password}" 459 username = "${aws_db_instance.bar.username}" 460 tags { 461 Name = "tf-replica-db" 462 } 463 } 464 `, val, val) 465 } 466 467 func testAccSnapshotInstanceConfig() string { 468 return fmt.Sprintf(` 469 provider "aws" { 470 region = "us-east-1" 471 } 472 resource "aws_db_instance" "snapshot" { 473 identifier = "tf-snapshot-%d" 474 475 allocated_storage = 5 476 engine = "mysql" 477 engine_version = "5.6.21" 478 instance_class = "db.t1.micro" 479 name = "baz" 480 password = "barbarbarbar" 481 username = "foo" 482 security_group_names = ["default"] 483 backup_retention_period = 1 484 485 parameter_group_name = "default.mysql5.6" 486 487 skip_final_snapshot = false 488 copy_tags_to_snapshot = true 489 final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-1" 490 tags { 491 Name = "tf-tags-db" 492 } 493 }`, acctest.RandInt()) 494 } 495 496 func testAccNoSnapshotInstanceConfig() string { 497 return fmt.Sprintf(` 498 provider "aws" { 499 region = "us-east-1" 500 } 501 resource "aws_db_instance" "no_snapshot" { 502 identifier = "tf-test-%s" 503 504 allocated_storage = 5 505 engine = "mysql" 506 engine_version = "5.6.21" 507 instance_class = "db.t1.micro" 508 name = "baz" 509 password = "barbarbarbar" 510 username = "foo" 511 security_group_names = ["default"] 512 backup_retention_period = 1 513 514 parameter_group_name = "default.mysql5.6" 515 516 skip_final_snapshot = true 517 final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-2" 518 } 519 `, acctest.RandString(5)) 520 } 521 522 var testAccSnapshotInstanceConfig_enhancedMonitoring = ` 523 resource "aws_iam_role" "enhanced_policy_role" { 524 name = "enhanced-monitoring-role" 525 assume_role_policy = <<EOF 526 { 527 "Version": "2012-10-17", 528 "Statement": [ 529 { 530 "Sid": "", 531 "Effect": "Allow", 532 "Principal": { 533 "Service": "monitoring.rds.amazonaws.com" 534 }, 535 "Action": "sts:AssumeRole" 536 } 537 ] 538 } 539 EOF 540 541 } 542 543 resource "aws_iam_policy_attachment" "test-attach" { 544 name = "enhanced-monitoring-attachment" 545 roles = [ 546 "${aws_iam_role.enhanced_policy_role.name}", 547 ] 548 549 policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" 550 } 551 552 resource "aws_db_instance" "enhanced_monitoring" { 553 identifier = "foobarbaz-test-terraform-enhanced-monitoring" 554 depends_on = ["aws_iam_policy_attachment.test-attach"] 555 556 allocated_storage = 5 557 engine = "mysql" 558 engine_version = "5.6.21" 559 instance_class = "db.m3.medium" 560 name = "baz" 561 password = "barbarbarbar" 562 username = "foo" 563 backup_retention_period = 1 564 565 parameter_group_name = "default.mysql5.6" 566 567 monitoring_role_arn = "${aws_iam_role.enhanced_policy_role.arn}" 568 monitoring_interval = "5" 569 570 skip_final_snapshot = true 571 } 572 `