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