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