github.com/acm1/terraform@v0.6.2-0.20150729164239-1f314444f45c/builtin/providers/aws/resource_aws_db_instance.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "regexp" 7 "strings" 8 "time" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/iam" 13 "github.com/aws/aws-sdk-go/service/rds" 14 15 "github.com/hashicorp/terraform/helper/resource" 16 "github.com/hashicorp/terraform/helper/schema" 17 ) 18 19 func resourceAwsDbInstance() *schema.Resource { 20 return &schema.Resource{ 21 Create: resourceAwsDbInstanceCreate, 22 Read: resourceAwsDbInstanceRead, 23 Update: resourceAwsDbInstanceUpdate, 24 Delete: resourceAwsDbInstanceDelete, 25 26 Schema: map[string]*schema.Schema{ 27 "name": &schema.Schema{ 28 Type: schema.TypeString, 29 Optional: true, 30 Computed: true, 31 ForceNew: true, 32 }, 33 34 "username": &schema.Schema{ 35 Type: schema.TypeString, 36 Required: true, 37 ForceNew: true, 38 }, 39 40 "password": &schema.Schema{ 41 Type: schema.TypeString, 42 Required: true, 43 }, 44 45 "engine": &schema.Schema{ 46 Type: schema.TypeString, 47 Required: true, 48 ForceNew: true, 49 StateFunc: func(v interface{}) string { 50 value := v.(string) 51 return strings.ToLower(value) 52 }, 53 }, 54 55 "engine_version": &schema.Schema{ 56 Type: schema.TypeString, 57 Required: true, 58 }, 59 60 "storage_encrypted": &schema.Schema{ 61 Type: schema.TypeBool, 62 Optional: true, 63 ForceNew: true, 64 }, 65 66 "allocated_storage": &schema.Schema{ 67 Type: schema.TypeInt, 68 Required: true, 69 }, 70 71 "storage_type": &schema.Schema{ 72 Type: schema.TypeString, 73 Optional: true, 74 Computed: true, 75 }, 76 77 "identifier": &schema.Schema{ 78 Type: schema.TypeString, 79 Required: true, 80 ForceNew: true, 81 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 82 value := v.(string) 83 if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { 84 errors = append(errors, fmt.Errorf( 85 "only lowercase alphanumeric characters and hyphens allowed in %q", k)) 86 } 87 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 88 errors = append(errors, fmt.Errorf( 89 "first character of %q must be a letter", k)) 90 } 91 if regexp.MustCompile(`--`).MatchString(value) { 92 errors = append(errors, fmt.Errorf( 93 "%q cannot contain two consecutive hyphens", k)) 94 } 95 if regexp.MustCompile(`-$`).MatchString(value) { 96 errors = append(errors, fmt.Errorf( 97 "%q cannot end with a hyphen", k)) 98 } 99 return 100 }, 101 }, 102 103 "instance_class": &schema.Schema{ 104 Type: schema.TypeString, 105 Required: true, 106 }, 107 108 "availability_zone": &schema.Schema{ 109 Type: schema.TypeString, 110 Optional: true, 111 Computed: true, 112 ForceNew: true, 113 }, 114 115 "backup_retention_period": &schema.Schema{ 116 Type: schema.TypeInt, 117 Optional: true, 118 Computed: true, 119 }, 120 121 "backup_window": &schema.Schema{ 122 Type: schema.TypeString, 123 Optional: true, 124 Computed: true, 125 }, 126 127 "iops": &schema.Schema{ 128 Type: schema.TypeInt, 129 Optional: true, 130 }, 131 132 "license_model": &schema.Schema{ 133 Type: schema.TypeString, 134 Optional: true, 135 Computed: true, 136 }, 137 138 "maintenance_window": &schema.Schema{ 139 Type: schema.TypeString, 140 Optional: true, 141 Computed: true, 142 }, 143 144 "multi_az": &schema.Schema{ 145 Type: schema.TypeBool, 146 Optional: true, 147 Computed: true, 148 }, 149 150 "port": &schema.Schema{ 151 Type: schema.TypeInt, 152 Optional: true, 153 Computed: true, 154 ForceNew: true, 155 }, 156 157 "publicly_accessible": &schema.Schema{ 158 Type: schema.TypeBool, 159 Optional: true, 160 ForceNew: true, 161 }, 162 163 "vpc_security_group_ids": &schema.Schema{ 164 Type: schema.TypeSet, 165 Optional: true, 166 Computed: true, 167 Elem: &schema.Schema{Type: schema.TypeString}, 168 Set: schema.HashString, 169 }, 170 171 "security_group_names": &schema.Schema{ 172 Type: schema.TypeSet, 173 Optional: true, 174 Elem: &schema.Schema{Type: schema.TypeString}, 175 Set: schema.HashString, 176 }, 177 178 "final_snapshot_identifier": &schema.Schema{ 179 Type: schema.TypeString, 180 Optional: true, 181 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 182 value := v.(string) 183 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 184 es = append(es, fmt.Errorf( 185 "only alphanumeric characters and hyphens allowed in %q", k)) 186 } 187 if regexp.MustCompile(`--`).MatchString(value) { 188 es = append(es, fmt.Errorf("%q cannot contain two consecutive hyphens", k)) 189 } 190 if regexp.MustCompile(`-$`).MatchString(value) { 191 es = append(es, fmt.Errorf("%q cannot end in a hyphen", k)) 192 } 193 return 194 }, 195 }, 196 197 "db_subnet_group_name": &schema.Schema{ 198 Type: schema.TypeString, 199 Optional: true, 200 ForceNew: true, 201 Computed: true, 202 }, 203 204 "parameter_group_name": &schema.Schema{ 205 Type: schema.TypeString, 206 Optional: true, 207 Computed: true, 208 }, 209 210 "address": &schema.Schema{ 211 Type: schema.TypeString, 212 Computed: true, 213 }, 214 215 "endpoint": &schema.Schema{ 216 Type: schema.TypeString, 217 Computed: true, 218 }, 219 220 "status": &schema.Schema{ 221 Type: schema.TypeString, 222 Computed: true, 223 }, 224 225 // apply_immediately is used to determine when the update modifications 226 // take place. 227 // See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html 228 "apply_immediately": &schema.Schema{ 229 Type: schema.TypeBool, 230 Optional: true, 231 Computed: true, 232 }, 233 234 "replicate_source_db": &schema.Schema{ 235 Type: schema.TypeString, 236 Optional: true, 237 }, 238 239 "replicas": &schema.Schema{ 240 Type: schema.TypeList, 241 Computed: true, 242 Elem: &schema.Schema{Type: schema.TypeString}, 243 }, 244 245 "snapshot_identifier": &schema.Schema{ 246 Type: schema.TypeString, 247 Computed: false, 248 Optional: true, 249 Elem: &schema.Schema{Type: schema.TypeString}, 250 }, 251 252 "auto_minor_version_upgrade": &schema.Schema{ 253 Type: schema.TypeBool, 254 Computed: false, 255 Optional: true, 256 }, 257 258 "tags": tagsSchema(), 259 }, 260 } 261 } 262 263 func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error { 264 conn := meta.(*AWSClient).rdsconn 265 tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) 266 267 if v, ok := d.GetOk("replicate_source_db"); ok { 268 opts := rds.CreateDBInstanceReadReplicaInput{ 269 SourceDBInstanceIdentifier: aws.String(v.(string)), 270 DBInstanceClass: aws.String(d.Get("instance_class").(string)), 271 DBInstanceIdentifier: aws.String(d.Get("identifier").(string)), 272 Tags: tags, 273 } 274 if attr, ok := d.GetOk("iops"); ok { 275 opts.IOPS = aws.Int64(int64(attr.(int))) 276 } 277 278 if attr, ok := d.GetOk("port"); ok { 279 opts.Port = aws.Int64(int64(attr.(int))) 280 } 281 282 if attr, ok := d.GetOk("availability_zone"); ok { 283 opts.AvailabilityZone = aws.String(attr.(string)) 284 } 285 286 if attr, ok := d.GetOk("publicly_accessible"); ok { 287 opts.PubliclyAccessible = aws.Bool(attr.(bool)) 288 } 289 _, err := conn.CreateDBInstanceReadReplica(&opts) 290 if err != nil { 291 return fmt.Errorf("Error creating DB Instance: %s", err) 292 } 293 } else if _, ok := d.GetOk("snapshot_identifier"); ok { 294 opts := rds.RestoreDBInstanceFromDBSnapshotInput{ 295 DBInstanceClass: aws.String(d.Get("instance_class").(string)), 296 DBInstanceIdentifier: aws.String(d.Get("identifier").(string)), 297 DBSnapshotIdentifier: aws.String(d.Get("snapshot_identifier").(string)), 298 Tags: tags, 299 } 300 301 if attr, ok := d.GetOk("auto_minor_version_upgrade"); ok { 302 opts.AutoMinorVersionUpgrade = aws.Bool(attr.(bool)) 303 } 304 305 if attr, ok := d.GetOk("availability_zone"); ok { 306 opts.AvailabilityZone = aws.String(attr.(string)) 307 } 308 309 if attr, ok := d.GetOk("db_subnet_group_name"); ok { 310 opts.DBSubnetGroupName = aws.String(attr.(string)) 311 } 312 313 if attr, ok := d.GetOk("engine"); ok { 314 opts.Engine = aws.String(attr.(string)) 315 } 316 317 if attr, ok := d.GetOk("iops"); ok { 318 opts.IOPS = aws.Int64(int64(attr.(int))) 319 } 320 321 if attr, ok := d.GetOk("license_model"); ok { 322 opts.LicenseModel = aws.String(attr.(string)) 323 } 324 325 if attr, ok := d.GetOk("multi_az"); ok { 326 opts.MultiAZ = aws.Bool(attr.(bool)) 327 } 328 329 if attr, ok := d.GetOk("option_group_name"); ok { 330 opts.OptionGroupName = aws.String(attr.(string)) 331 } 332 333 if attr, ok := d.GetOk("port"); ok { 334 opts.Port = aws.Int64(int64(attr.(int))) 335 } 336 337 if attr, ok := d.GetOk("publicly_accessible"); ok { 338 opts.PubliclyAccessible = aws.Bool(attr.(bool)) 339 } 340 341 if attr, ok := d.GetOk("tde_credential_arn"); ok { 342 opts.TDECredentialARN = aws.String(attr.(string)) 343 } 344 345 if attr, ok := d.GetOk("storage_type"); ok { 346 opts.StorageType = aws.String(attr.(string)) 347 } 348 349 _, err := conn.RestoreDBInstanceFromDBSnapshot(&opts) 350 if err != nil { 351 return fmt.Errorf("Error creating DB Instance: %s", err) 352 } 353 } else { 354 opts := rds.CreateDBInstanceInput{ 355 AllocatedStorage: aws.Int64(int64(d.Get("allocated_storage").(int))), 356 DBName: aws.String(d.Get("name").(string)), 357 DBInstanceClass: aws.String(d.Get("instance_class").(string)), 358 DBInstanceIdentifier: aws.String(d.Get("identifier").(string)), 359 MasterUsername: aws.String(d.Get("username").(string)), 360 MasterUserPassword: aws.String(d.Get("password").(string)), 361 Engine: aws.String(d.Get("engine").(string)), 362 EngineVersion: aws.String(d.Get("engine_version").(string)), 363 StorageEncrypted: aws.Bool(d.Get("storage_encrypted").(bool)), 364 Tags: tags, 365 } 366 367 attr := d.Get("backup_retention_period") 368 opts.BackupRetentionPeriod = aws.Int64(int64(attr.(int))) 369 if attr, ok := d.GetOk("multi_az"); ok { 370 opts.MultiAZ = aws.Bool(attr.(bool)) 371 } 372 373 if attr, ok := d.GetOk("maintenance_window"); ok { 374 opts.PreferredMaintenanceWindow = aws.String(attr.(string)) 375 } 376 377 if attr, ok := d.GetOk("backup_window"); ok { 378 opts.PreferredBackupWindow = aws.String(attr.(string)) 379 } 380 381 if attr, ok := d.GetOk("license_model"); ok { 382 opts.LicenseModel = aws.String(attr.(string)) 383 } 384 if attr, ok := d.GetOk("parameter_group_name"); ok { 385 opts.DBParameterGroupName = aws.String(attr.(string)) 386 } 387 388 if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { 389 var s []*string 390 for _, v := range attr.List() { 391 s = append(s, aws.String(v.(string))) 392 } 393 opts.VPCSecurityGroupIDs = s 394 } 395 396 if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 { 397 var s []*string 398 for _, v := range attr.List() { 399 s = append(s, aws.String(v.(string))) 400 } 401 opts.DBSecurityGroups = s 402 } 403 if attr, ok := d.GetOk("storage_type"); ok { 404 opts.StorageType = aws.String(attr.(string)) 405 } 406 407 if attr, ok := d.GetOk("db_subnet_group_name"); ok { 408 opts.DBSubnetGroupName = aws.String(attr.(string)) 409 } 410 411 if attr, ok := d.GetOk("iops"); ok { 412 opts.IOPS = aws.Int64(int64(attr.(int))) 413 } 414 415 if attr, ok := d.GetOk("port"); ok { 416 opts.Port = aws.Int64(int64(attr.(int))) 417 } 418 419 if attr, ok := d.GetOk("availability_zone"); ok { 420 opts.AvailabilityZone = aws.String(attr.(string)) 421 } 422 423 if attr, ok := d.GetOk("publicly_accessible"); ok { 424 opts.PubliclyAccessible = aws.Bool(attr.(bool)) 425 } 426 427 log.Printf("[DEBUG] DB Instance create configuration: %#v", opts) 428 var err error 429 _, err = conn.CreateDBInstance(&opts) 430 if err != nil { 431 return fmt.Errorf("Error creating DB Instance: %s", err) 432 } 433 } 434 435 d.SetId(d.Get("identifier").(string)) 436 437 log.Printf("[INFO] DB Instance ID: %s", d.Id()) 438 439 log.Println( 440 "[INFO] Waiting for DB Instance to be available") 441 442 stateConf := &resource.StateChangeConf{ 443 Pending: []string{"creating", "backing-up", "modifying"}, 444 Target: "available", 445 Refresh: resourceAwsDbInstanceStateRefreshFunc(d, meta), 446 Timeout: 40 * time.Minute, 447 MinTimeout: 10 * time.Second, 448 Delay: 30 * time.Second, // Wait 30 secs before starting 449 } 450 451 // Wait, catching any errors 452 _, err := stateConf.WaitForState() 453 if err != nil { 454 return err 455 } 456 457 return resourceAwsDbInstanceRead(d, meta) 458 } 459 460 func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error { 461 v, err := resourceAwsDbInstanceRetrieve(d, meta) 462 463 if err != nil { 464 return err 465 } 466 if v == nil { 467 d.SetId("") 468 return nil 469 } 470 471 d.Set("name", v.DBName) 472 d.Set("username", v.MasterUsername) 473 d.Set("engine", v.Engine) 474 d.Set("engine_version", v.EngineVersion) 475 d.Set("allocated_storage", v.AllocatedStorage) 476 d.Set("storage_type", v.StorageType) 477 d.Set("instance_class", v.DBInstanceClass) 478 d.Set("availability_zone", v.AvailabilityZone) 479 d.Set("backup_retention_period", v.BackupRetentionPeriod) 480 d.Set("backup_window", v.PreferredBackupWindow) 481 d.Set("license_model", v.LicenseModel) 482 d.Set("maintenance_window", v.PreferredMaintenanceWindow) 483 d.Set("multi_az", v.MultiAZ) 484 if v.DBSubnetGroup != nil { 485 d.Set("db_subnet_group_name", v.DBSubnetGroup.DBSubnetGroupName) 486 } 487 488 if len(v.DBParameterGroups) > 0 { 489 d.Set("parameter_group_name", v.DBParameterGroups[0].DBParameterGroupName) 490 } 491 492 if v.Endpoint != nil { 493 d.Set("port", v.Endpoint.Port) 494 d.Set("address", v.Endpoint.Address) 495 496 if v.Endpoint.Address != nil && v.Endpoint.Port != nil { 497 d.Set("endpoint", 498 fmt.Sprintf("%s:%d", *v.Endpoint.Address, *v.Endpoint.Port)) 499 } 500 } 501 502 d.Set("status", v.DBInstanceStatus) 503 d.Set("storage_encrypted", v.StorageEncrypted) 504 505 // list tags for resource 506 // set tags 507 conn := meta.(*AWSClient).rdsconn 508 arn, err := buildRDSARN(d, meta) 509 if err != nil { 510 name := "<empty>" 511 if v.DBName != nil && *v.DBName != "" { 512 name = *v.DBName 513 } 514 515 log.Printf("[DEBUG] Error building ARN for DB Instance, not setting Tags for DB %s", name) 516 } else { 517 resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{ 518 ResourceName: aws.String(arn), 519 }) 520 521 if err != nil { 522 log.Printf("[DEBUG] Error retreiving tags for ARN: %s", arn) 523 } 524 525 var dt []*rds.Tag 526 if len(resp.TagList) > 0 { 527 dt = resp.TagList 528 } 529 d.Set("tags", tagsToMapRDS(dt)) 530 } 531 532 // Create an empty schema.Set to hold all vpc security group ids 533 ids := &schema.Set{ 534 F: schema.HashString, 535 } 536 for _, v := range v.VPCSecurityGroups { 537 ids.Add(*v.VPCSecurityGroupID) 538 } 539 d.Set("vpc_security_group_ids", ids) 540 541 // Create an empty schema.Set to hold all security group names 542 sgn := &schema.Set{ 543 F: schema.HashString, 544 } 545 for _, v := range v.DBSecurityGroups { 546 sgn.Add(*v.DBSecurityGroupName) 547 } 548 d.Set("security_group_names", sgn) 549 550 // replica things 551 552 var replicas []string 553 for _, v := range v.ReadReplicaDBInstanceIdentifiers { 554 replicas = append(replicas, *v) 555 } 556 if err := d.Set("replicas", replicas); err != nil { 557 return fmt.Errorf("[DEBUG] Error setting replicas attribute: %#v, error: %#v", replicas, err) 558 } 559 560 d.Set("replicate_source_db", v.ReadReplicaSourceDBInstanceIdentifier) 561 562 return nil 563 } 564 565 func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error { 566 conn := meta.(*AWSClient).rdsconn 567 568 log.Printf("[DEBUG] DB Instance destroy: %v", d.Id()) 569 570 opts := rds.DeleteDBInstanceInput{DBInstanceIdentifier: aws.String(d.Id())} 571 572 finalSnapshot := d.Get("final_snapshot_identifier").(string) 573 if finalSnapshot == "" { 574 opts.SkipFinalSnapshot = aws.Bool(true) 575 } else { 576 opts.FinalDBSnapshotIdentifier = aws.String(finalSnapshot) 577 } 578 579 log.Printf("[DEBUG] DB Instance destroy configuration: %v", opts) 580 if _, err := conn.DeleteDBInstance(&opts); err != nil { 581 return err 582 } 583 584 log.Println( 585 "[INFO] Waiting for DB Instance to be destroyed") 586 stateConf := &resource.StateChangeConf{ 587 Pending: []string{"creating", "backing-up", 588 "modifying", "deleting", "available"}, 589 Target: "", 590 Refresh: resourceAwsDbInstanceStateRefreshFunc(d, meta), 591 Timeout: 40 * time.Minute, 592 MinTimeout: 10 * time.Second, 593 Delay: 30 * time.Second, // Wait 30 secs before starting 594 } 595 if _, err := stateConf.WaitForState(); err != nil { 596 return err 597 } 598 599 return nil 600 } 601 602 func resourceAwsDbInstanceUpdate(d *schema.ResourceData, meta interface{}) error { 603 conn := meta.(*AWSClient).rdsconn 604 605 d.Partial(true) 606 607 req := &rds.ModifyDBInstanceInput{ 608 ApplyImmediately: aws.Bool(d.Get("apply_immediately").(bool)), 609 DBInstanceIdentifier: aws.String(d.Id()), 610 } 611 d.SetPartial("apply_immediately") 612 613 requestUpdate := false 614 if d.HasChange("allocated_storage") { 615 d.SetPartial("allocated_storage") 616 req.AllocatedStorage = aws.Int64(int64(d.Get("allocated_storage").(int))) 617 requestUpdate = true 618 } 619 if d.HasChange("backup_retention_period") { 620 d.SetPartial("backup_retention_period") 621 req.BackupRetentionPeriod = aws.Int64(int64(d.Get("backup_retention_period").(int))) 622 requestUpdate = true 623 } 624 if d.HasChange("instance_class") { 625 d.SetPartial("instance_class") 626 req.DBInstanceClass = aws.String(d.Get("instance_class").(string)) 627 requestUpdate = true 628 } 629 if d.HasChange("parameter_group_name") { 630 d.SetPartial("parameter_group_name") 631 req.DBParameterGroupName = aws.String(d.Get("parameter_group_name").(string)) 632 requestUpdate = true 633 } 634 if d.HasChange("engine_version") { 635 d.SetPartial("engine_version") 636 req.EngineVersion = aws.String(d.Get("engine_version").(string)) 637 requestUpdate = true 638 } 639 if d.HasChange("iops") { 640 d.SetPartial("iops") 641 req.IOPS = aws.Int64(int64(d.Get("iops").(int))) 642 requestUpdate = true 643 } 644 if d.HasChange("backup_window") { 645 d.SetPartial("backup_window") 646 req.PreferredBackupWindow = aws.String(d.Get("backup_window").(string)) 647 requestUpdate = true 648 } 649 if d.HasChange("maintenance_window") { 650 d.SetPartial("maintenance_window") 651 req.PreferredMaintenanceWindow = aws.String(d.Get("maintenance_window").(string)) 652 requestUpdate = true 653 } 654 if d.HasChange("password") { 655 d.SetPartial("password") 656 req.MasterUserPassword = aws.String(d.Get("password").(string)) 657 requestUpdate = true 658 } 659 if d.HasChange("multi_az") { 660 d.SetPartial("multi_az") 661 req.MultiAZ = aws.Bool(d.Get("multi_az").(bool)) 662 requestUpdate = true 663 } 664 if d.HasChange("storage_type") { 665 d.SetPartial("storage_type") 666 req.StorageType = aws.String(d.Get("storage_type").(string)) 667 requestUpdate = true 668 } 669 670 if d.HasChange("vpc_security_group_ids") { 671 if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { 672 var s []*string 673 for _, v := range attr.List() { 674 s = append(s, aws.String(v.(string))) 675 } 676 req.VPCSecurityGroupIDs = s 677 } 678 requestUpdate = true 679 } 680 681 if d.HasChange("vpc_security_group_ids") { 682 if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 { 683 var s []*string 684 for _, v := range attr.List() { 685 s = append(s, aws.String(v.(string))) 686 } 687 req.DBSecurityGroups = s 688 } 689 requestUpdate = true 690 } 691 692 log.Printf("[DEBUG] Send DB Instance Modification request: %#v", requestUpdate) 693 if requestUpdate { 694 log.Printf("[DEBUG] DB Instance Modification request: %#v", req) 695 _, err := conn.ModifyDBInstance(req) 696 if err != nil { 697 return fmt.Errorf("Error modifying DB Instance %s: %s", d.Id(), err) 698 } 699 } 700 701 // seperate request to promote a database 702 if d.HasChange("replicate_source_db") { 703 if d.Get("replicate_source_db").(string) == "" { 704 // promote 705 opts := rds.PromoteReadReplicaInput{ 706 DBInstanceIdentifier: aws.String(d.Id()), 707 } 708 attr := d.Get("backup_retention_period") 709 opts.BackupRetentionPeriod = aws.Int64(int64(attr.(int))) 710 if attr, ok := d.GetOk("backup_window"); ok { 711 opts.PreferredBackupWindow = aws.String(attr.(string)) 712 } 713 _, err := conn.PromoteReadReplica(&opts) 714 if err != nil { 715 return fmt.Errorf("Error promoting database: %#v", err) 716 } 717 d.Set("replicate_source_db", "") 718 } else { 719 return fmt.Errorf("cannot elect new source database for replication") 720 } 721 } 722 723 if arn, err := buildRDSARN(d, meta); err == nil { 724 if err := setTagsRDS(conn, d, arn); err != nil { 725 return err 726 } else { 727 d.SetPartial("tags") 728 } 729 } 730 d.Partial(false) 731 return resourceAwsDbInstanceRead(d, meta) 732 } 733 734 func resourceAwsDbInstanceRetrieve( 735 d *schema.ResourceData, meta interface{}) (*rds.DBInstance, error) { 736 conn := meta.(*AWSClient).rdsconn 737 738 opts := rds.DescribeDBInstancesInput{ 739 DBInstanceIdentifier: aws.String(d.Id()), 740 } 741 742 log.Printf("[DEBUG] DB Instance describe configuration: %#v", opts) 743 744 resp, err := conn.DescribeDBInstances(&opts) 745 746 if err != nil { 747 dbinstanceerr, ok := err.(awserr.Error) 748 if ok && dbinstanceerr.Code() == "DBInstanceNotFound" { 749 return nil, nil 750 } 751 return nil, fmt.Errorf("Error retrieving DB Instances: %s", err) 752 } 753 754 if len(resp.DBInstances) != 1 || 755 *resp.DBInstances[0].DBInstanceIdentifier != d.Id() { 756 if err != nil { 757 return nil, nil 758 } 759 } 760 761 return resp.DBInstances[0], nil 762 } 763 764 func resourceAwsDbInstanceStateRefreshFunc( 765 d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc { 766 return func() (interface{}, string, error) { 767 v, err := resourceAwsDbInstanceRetrieve(d, meta) 768 769 if err != nil { 770 log.Printf("Error on retrieving DB Instance when waiting: %s", err) 771 return nil, "", err 772 } 773 774 if v == nil { 775 return nil, "", nil 776 } 777 778 if v.DBInstanceStatus != nil { 779 log.Printf("[DEBUG] DB Instance status for instance %s: %s", d.Id(), *v.DBInstanceStatus) 780 } 781 782 return v, *v.DBInstanceStatus, nil 783 } 784 } 785 786 func buildRDSARN(d *schema.ResourceData, meta interface{}) (string, error) { 787 iamconn := meta.(*AWSClient).iamconn 788 region := meta.(*AWSClient).region 789 // An zero value GetUserInput{} defers to the currently logged in user 790 resp, err := iamconn.GetUser(&iam.GetUserInput{}) 791 if err != nil { 792 return "", err 793 } 794 userARN := *resp.User.ARN 795 accountID := strings.Split(userARN, ":")[4] 796 arn := fmt.Sprintf("arn:aws:rds:%s:%s:db:%s", region, accountID, d.Id()) 797 return arn, nil 798 }