github.com/articulate/terraform@v0.6.13-0.20160303003731-8d31c93862de/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 = fmt.Sprintf(` 366 resource "aws_db_instance" "bar" { 367 identifier = "foobarbaz-test-terraform-%d" 368 369 allocated_storage = 10 370 engine = "MySQL" 371 engine_version = "5.6.21" 372 instance_class = "db.t1.micro" 373 name = "baz" 374 password = "barbarbarbar" 375 username = "foo" 376 377 378 # Maintenance Window is stored in lower case in the API, though not strictly 379 # documented. Terraform will downcase this to match (as opposed to throw a 380 # validation error). 381 maintenance_window = "Fri:09:00-Fri:09:30" 382 383 backup_retention_period = 0 384 385 parameter_group_name = "default.mysql5.6" 386 }`, rand.New(rand.NewSource(time.Now().UnixNano())).Int()) 387 388 func testAccReplicaInstanceConfig(val int) string { 389 return fmt.Sprintf(` 390 resource "aws_db_instance" "bar" { 391 identifier = "foobarbaz-test-terraform-%d" 392 393 allocated_storage = 5 394 engine = "mysql" 395 engine_version = "5.6.21" 396 instance_class = "db.t1.micro" 397 name = "baz" 398 password = "barbarbarbar" 399 username = "foo" 400 401 backup_retention_period = 1 402 403 parameter_group_name = "default.mysql5.6" 404 } 405 406 resource "aws_db_instance" "replica" { 407 identifier = "tf-replica-db-%d" 408 backup_retention_period = 0 409 replicate_source_db = "${aws_db_instance.bar.identifier}" 410 allocated_storage = "${aws_db_instance.bar.allocated_storage}" 411 engine = "${aws_db_instance.bar.engine}" 412 engine_version = "${aws_db_instance.bar.engine_version}" 413 instance_class = "${aws_db_instance.bar.instance_class}" 414 password = "${aws_db_instance.bar.password}" 415 username = "${aws_db_instance.bar.username}" 416 tags { 417 Name = "tf-replica-db" 418 } 419 } 420 `, val, val) 421 } 422 423 func testAccSnapshotInstanceConfig() string { 424 return fmt.Sprintf(` 425 provider "aws" { 426 region = "us-east-1" 427 } 428 resource "aws_db_instance" "snapshot" { 429 identifier = "tf-snapshot-%d" 430 431 allocated_storage = 5 432 engine = "mysql" 433 engine_version = "5.6.21" 434 instance_class = "db.t1.micro" 435 name = "baz" 436 password = "barbarbarbar" 437 username = "foo" 438 security_group_names = ["default"] 439 backup_retention_period = 1 440 441 parameter_group_name = "default.mysql5.6" 442 443 skip_final_snapshot = false 444 copy_tags_to_snapshot = true 445 final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-1" 446 tags { 447 Name = "tf-tags-db" 448 } 449 }`, acctest.RandInt()) 450 } 451 452 var testAccNoSnapshotInstanceConfig = ` 453 provider "aws" { 454 region = "us-east-1" 455 } 456 resource "aws_db_instance" "no_snapshot" { 457 identifier = "foobarbaz-test-terraform-snapshot-2" 458 459 allocated_storage = 5 460 engine = "mysql" 461 engine_version = "5.6.21" 462 instance_class = "db.t1.micro" 463 name = "baz" 464 password = "barbarbarbar" 465 username = "foo" 466 security_group_names = ["default"] 467 backup_retention_period = 1 468 469 parameter_group_name = "default.mysql5.6" 470 471 skip_final_snapshot = true 472 final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-2" 473 } 474 ` 475 476 var testAccSnapshotInstanceConfig_enhancedMonitoring = ` 477 provider "aws" { 478 region = "us-east-1" 479 } 480 481 resource "aws_iam_role" "enhanced_policy_role" { 482 name = "enhanced-monitoring-role" 483 assume_role_policy = <<EOF 484 { 485 "Version": "2012-10-17", 486 "Statement": [ 487 { 488 "Sid": "", 489 "Effect": "Allow", 490 "Principal": { 491 "Service": "monitoring.rds.amazonaws.com" 492 }, 493 "Action": "sts:AssumeRole" 494 } 495 ] 496 } 497 EOF 498 499 } 500 501 resource "aws_iam_policy_attachment" "test-attach" { 502 name = "enhanced-monitoring-attachment" 503 roles = [ 504 "${aws_iam_role.enhanced_policy_role.name}", 505 ] 506 507 policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" 508 } 509 510 resource "aws_db_instance" "enhanced_monitoring" { 511 identifier = "foobarbaz-test-terraform-enhanced-monitoring" 512 depends_on = ["aws_iam_policy_attachment.test-attach"] 513 514 allocated_storage = 5 515 engine = "mysql" 516 engine_version = "5.6.21" 517 instance_class = "db.t2.small" 518 name = "baz" 519 password = "barbarbarbar" 520 username = "foo" 521 backup_retention_period = 1 522 523 parameter_group_name = "default.mysql5.6" 524 525 monitoring_role_arn = "${aws_iam_role.enhanced_policy_role.arn}" 526 monitoring_interval = "5" 527 528 skip_final_snapshot = true 529 } 530 `