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