github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_rds_cluster.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/rds" 13 "github.com/hashicorp/terraform/helper/resource" 14 "github.com/hashicorp/terraform/helper/schema" 15 ) 16 17 func resourceAwsRDSCluster() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceAwsRDSClusterCreate, 20 Read: resourceAwsRDSClusterRead, 21 Update: resourceAwsRDSClusterUpdate, 22 Delete: resourceAwsRDSClusterDelete, 23 Importer: &schema.ResourceImporter{ 24 State: resourceAwsRdsClusterImport, 25 }, 26 27 Schema: map[string]*schema.Schema{ 28 29 "availability_zones": { 30 Type: schema.TypeSet, 31 Elem: &schema.Schema{Type: schema.TypeString}, 32 Optional: true, 33 ForceNew: true, 34 Computed: true, 35 Set: schema.HashString, 36 }, 37 38 "cluster_identifier": { 39 Type: schema.TypeString, 40 Optional: true, 41 Computed: true, 42 ForceNew: true, 43 ConflictsWith: []string{"cluster_identifier_prefix"}, 44 ValidateFunc: validateRdsIdentifier, 45 }, 46 "cluster_identifier_prefix": { 47 Type: schema.TypeString, 48 Optional: true, 49 Computed: true, 50 ForceNew: true, 51 ValidateFunc: validateRdsIdentifierPrefix, 52 }, 53 54 "cluster_members": { 55 Type: schema.TypeSet, 56 Elem: &schema.Schema{Type: schema.TypeString}, 57 Optional: true, 58 Computed: true, 59 Set: schema.HashString, 60 }, 61 62 "database_name": { 63 Type: schema.TypeString, 64 Optional: true, 65 Computed: true, 66 ForceNew: true, 67 }, 68 69 "db_subnet_group_name": { 70 Type: schema.TypeString, 71 Optional: true, 72 ForceNew: true, 73 Computed: true, 74 }, 75 76 "db_cluster_parameter_group_name": { 77 Type: schema.TypeString, 78 Optional: true, 79 Computed: true, 80 }, 81 82 "endpoint": { 83 Type: schema.TypeString, 84 Computed: true, 85 }, 86 87 "reader_endpoint": { 88 Type: schema.TypeString, 89 Computed: true, 90 }, 91 92 "engine": { 93 Type: schema.TypeString, 94 Computed: true, 95 }, 96 97 "storage_encrypted": { 98 Type: schema.TypeBool, 99 Optional: true, 100 Default: false, 101 ForceNew: true, 102 }, 103 104 "final_snapshot_identifier": { 105 Type: schema.TypeString, 106 Optional: true, 107 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 108 value := v.(string) 109 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 110 es = append(es, fmt.Errorf( 111 "only alphanumeric characters and hyphens allowed in %q", k)) 112 } 113 if regexp.MustCompile(`--`).MatchString(value) { 114 es = append(es, fmt.Errorf("%q cannot contain two consecutive hyphens", k)) 115 } 116 if regexp.MustCompile(`-$`).MatchString(value) { 117 es = append(es, fmt.Errorf("%q cannot end in a hyphen", k)) 118 } 119 return 120 }, 121 }, 122 123 "skip_final_snapshot": { 124 Type: schema.TypeBool, 125 Optional: true, 126 Default: false, 127 }, 128 129 "master_username": { 130 Type: schema.TypeString, 131 Computed: true, 132 Optional: true, 133 ForceNew: true, 134 }, 135 136 "master_password": { 137 Type: schema.TypeString, 138 Optional: true, 139 Sensitive: true, 140 }, 141 142 "snapshot_identifier": { 143 Type: schema.TypeString, 144 Computed: false, 145 Optional: true, 146 Elem: &schema.Schema{Type: schema.TypeString}, 147 }, 148 149 "port": { 150 Type: schema.TypeInt, 151 Optional: true, 152 Computed: true, 153 }, 154 155 // apply_immediately is used to determine when the update modifications 156 // take place. 157 // See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html 158 "apply_immediately": { 159 Type: schema.TypeBool, 160 Optional: true, 161 Computed: true, 162 }, 163 164 "vpc_security_group_ids": { 165 Type: schema.TypeSet, 166 Optional: true, 167 Computed: true, 168 Elem: &schema.Schema{Type: schema.TypeString}, 169 Set: schema.HashString, 170 }, 171 172 "preferred_backup_window": { 173 Type: schema.TypeString, 174 Optional: true, 175 Computed: true, 176 ValidateFunc: validateOnceADayWindowFormat, 177 }, 178 179 "preferred_maintenance_window": { 180 Type: schema.TypeString, 181 Optional: true, 182 Computed: true, 183 StateFunc: func(val interface{}) string { 184 if val == nil { 185 return "" 186 } 187 return strings.ToLower(val.(string)) 188 }, 189 ValidateFunc: validateOnceAWeekWindowFormat, 190 }, 191 192 "backup_retention_period": { 193 Type: schema.TypeInt, 194 Optional: true, 195 Default: 1, 196 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 197 value := v.(int) 198 if value > 35 { 199 es = append(es, fmt.Errorf( 200 "backup retention period cannot be more than 35 days")) 201 } 202 return 203 }, 204 }, 205 206 "kms_key_id": { 207 Type: schema.TypeString, 208 Optional: true, 209 Computed: true, 210 ForceNew: true, 211 ValidateFunc: validateArn, 212 }, 213 214 "replication_source_identifier": { 215 Type: schema.TypeString, 216 Optional: true, 217 }, 218 219 "tags": tagsSchema(), 220 }, 221 } 222 } 223 224 func resourceAwsRdsClusterImport( 225 d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { 226 // Neither skip_final_snapshot nor final_snapshot_identifier can be fetched 227 // from any API call, so we need to default skip_final_snapshot to true so 228 // that final_snapshot_identifier is not required 229 d.Set("skip_final_snapshot", true) 230 return []*schema.ResourceData{d}, nil 231 } 232 233 func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error { 234 conn := meta.(*AWSClient).rdsconn 235 tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) 236 237 var identifier string 238 if v, ok := d.GetOk("cluster_identifier"); ok { 239 identifier = v.(string) 240 } else { 241 if v, ok := d.GetOk("cluster_identifier_prefix"); ok { 242 identifier = resource.PrefixedUniqueId(v.(string)) 243 } else { 244 identifier = resource.PrefixedUniqueId("tf-") 245 } 246 247 d.Set("cluster_identifier", identifier) 248 } 249 250 if _, ok := d.GetOk("snapshot_identifier"); ok { 251 opts := rds.RestoreDBClusterFromSnapshotInput{ 252 DBClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)), 253 SnapshotIdentifier: aws.String(d.Get("snapshot_identifier").(string)), 254 Engine: aws.String("aurora"), 255 Tags: tags, 256 } 257 258 if attr := d.Get("availability_zones").(*schema.Set); attr.Len() > 0 { 259 opts.AvailabilityZones = expandStringList(attr.List()) 260 } 261 262 if attr, ok := d.GetOk("db_subnet_group_name"); ok { 263 opts.DBSubnetGroupName = aws.String(attr.(string)) 264 } 265 266 if attr, ok := d.GetOk("database_name"); ok { 267 opts.DatabaseName = aws.String(attr.(string)) 268 } 269 270 if attr, ok := d.GetOk("option_group_name"); ok { 271 opts.OptionGroupName = aws.String(attr.(string)) 272 } 273 274 if attr, ok := d.GetOk("port"); ok { 275 opts.Port = aws.Int64(int64(attr.(int))) 276 } 277 278 var sgUpdate bool 279 if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { 280 sgUpdate = true 281 opts.VpcSecurityGroupIds = expandStringList(attr.List()) 282 } 283 284 log.Printf("[DEBUG] RDS Cluster restore from snapshot configuration: %s", opts) 285 _, err := conn.RestoreDBClusterFromSnapshot(&opts) 286 if err != nil { 287 return fmt.Errorf("Error creating RDS Cluster: %s", err) 288 } 289 290 if sgUpdate { 291 log.Printf("[INFO] RDS Cluster is restoring from snapshot with default security, but custom security should be set, will now update after snapshot is restored!") 292 293 d.SetId(d.Get("cluster_identifier").(string)) 294 295 log.Printf("[INFO] RDS Cluster Instance ID: %s", d.Id()) 296 297 log.Println("[INFO] Waiting for RDS Cluster to be available") 298 299 stateConf := &resource.StateChangeConf{ 300 Pending: []string{"creating", "backing-up", "modifying"}, 301 Target: []string{"available"}, 302 Refresh: resourceAwsRDSClusterStateRefreshFunc(d, meta), 303 Timeout: 120 * time.Minute, 304 MinTimeout: 3 * time.Second, 305 Delay: 30 * time.Second, // Wait 30 secs before starting 306 } 307 308 // Wait, catching any errors 309 _, err := stateConf.WaitForState() 310 if err != nil { 311 return err 312 } 313 314 err = resourceAwsRDSClusterInstanceUpdate(d, meta) 315 if err != nil { 316 return err 317 } 318 } 319 } else if _, ok := d.GetOk("replication_source_identifier"); ok { 320 createOpts := &rds.CreateDBClusterInput{ 321 DBClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)), 322 Engine: aws.String("aurora"), 323 StorageEncrypted: aws.Bool(d.Get("storage_encrypted").(bool)), 324 ReplicationSourceIdentifier: aws.String(d.Get("replication_source_identifier").(string)), 325 Tags: tags, 326 } 327 328 if attr, ok := d.GetOk("port"); ok { 329 createOpts.Port = aws.Int64(int64(attr.(int))) 330 } 331 332 if attr, ok := d.GetOk("db_subnet_group_name"); ok { 333 createOpts.DBSubnetGroupName = aws.String(attr.(string)) 334 } 335 336 if attr, ok := d.GetOk("db_cluster_parameter_group_name"); ok { 337 createOpts.DBClusterParameterGroupName = aws.String(attr.(string)) 338 } 339 340 if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { 341 createOpts.VpcSecurityGroupIds = expandStringList(attr.List()) 342 } 343 344 if attr := d.Get("availability_zones").(*schema.Set); attr.Len() > 0 { 345 createOpts.AvailabilityZones = expandStringList(attr.List()) 346 } 347 348 if v, ok := d.GetOk("backup_retention_period"); ok { 349 createOpts.BackupRetentionPeriod = aws.Int64(int64(v.(int))) 350 } 351 352 if v, ok := d.GetOk("preferred_backup_window"); ok { 353 createOpts.PreferredBackupWindow = aws.String(v.(string)) 354 } 355 356 if v, ok := d.GetOk("preferred_maintenance_window"); ok { 357 createOpts.PreferredMaintenanceWindow = aws.String(v.(string)) 358 } 359 360 if attr, ok := d.GetOk("kms_key_id"); ok { 361 createOpts.KmsKeyId = aws.String(attr.(string)) 362 } 363 364 log.Printf("[DEBUG] Create RDS Cluster as read replica: %s", createOpts) 365 resp, err := conn.CreateDBCluster(createOpts) 366 if err != nil { 367 log.Printf("[ERROR] Error creating RDS Cluster: %s", err) 368 return err 369 } 370 371 log.Printf("[DEBUG]: RDS Cluster create response: %s", resp) 372 373 } else { 374 if _, ok := d.GetOk("master_password"); !ok { 375 return fmt.Errorf(`provider.aws: aws_rds_cluster: %s: "master_password": required field is not set`, d.Get("database_name").(string)) 376 } 377 378 if _, ok := d.GetOk("master_username"); !ok { 379 return fmt.Errorf(`provider.aws: aws_rds_cluster: %s: "master_username": required field is not set`, d.Get("database_name").(string)) 380 } 381 382 createOpts := &rds.CreateDBClusterInput{ 383 DBClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)), 384 Engine: aws.String("aurora"), 385 MasterUserPassword: aws.String(d.Get("master_password").(string)), 386 MasterUsername: aws.String(d.Get("master_username").(string)), 387 StorageEncrypted: aws.Bool(d.Get("storage_encrypted").(bool)), 388 Tags: tags, 389 } 390 391 if v := d.Get("database_name"); v.(string) != "" { 392 createOpts.DatabaseName = aws.String(v.(string)) 393 } 394 395 if attr, ok := d.GetOk("port"); ok { 396 createOpts.Port = aws.Int64(int64(attr.(int))) 397 } 398 399 if attr, ok := d.GetOk("db_subnet_group_name"); ok { 400 createOpts.DBSubnetGroupName = aws.String(attr.(string)) 401 } 402 403 if attr, ok := d.GetOk("db_cluster_parameter_group_name"); ok { 404 createOpts.DBClusterParameterGroupName = aws.String(attr.(string)) 405 } 406 407 if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { 408 createOpts.VpcSecurityGroupIds = expandStringList(attr.List()) 409 } 410 411 if attr := d.Get("availability_zones").(*schema.Set); attr.Len() > 0 { 412 createOpts.AvailabilityZones = expandStringList(attr.List()) 413 } 414 415 if v, ok := d.GetOk("backup_retention_period"); ok { 416 createOpts.BackupRetentionPeriod = aws.Int64(int64(v.(int))) 417 } 418 419 if v, ok := d.GetOk("preferred_backup_window"); ok { 420 createOpts.PreferredBackupWindow = aws.String(v.(string)) 421 } 422 423 if v, ok := d.GetOk("preferred_maintenance_window"); ok { 424 createOpts.PreferredMaintenanceWindow = aws.String(v.(string)) 425 } 426 427 if attr, ok := d.GetOk("kms_key_id"); ok { 428 createOpts.KmsKeyId = aws.String(attr.(string)) 429 } 430 431 log.Printf("[DEBUG] RDS Cluster create options: %s", createOpts) 432 resp, err := conn.CreateDBCluster(createOpts) 433 if err != nil { 434 log.Printf("[ERROR] Error creating RDS Cluster: %s", err) 435 return err 436 } 437 438 log.Printf("[DEBUG]: RDS Cluster create response: %s", resp) 439 } 440 441 d.SetId(d.Get("cluster_identifier").(string)) 442 443 log.Printf("[INFO] RDS Cluster ID: %s", d.Id()) 444 445 log.Println( 446 "[INFO] Waiting for RDS Cluster to be available") 447 448 stateConf := &resource.StateChangeConf{ 449 Pending: []string{"creating", "backing-up", "modifying"}, 450 Target: []string{"available"}, 451 Refresh: resourceAwsRDSClusterStateRefreshFunc(d, meta), 452 Timeout: 120 * time.Minute, 453 MinTimeout: 3 * time.Second, 454 } 455 456 // Wait, catching any errors 457 _, err := stateConf.WaitForState() 458 if err != nil { 459 return fmt.Errorf("[WARN] Error waiting for RDS Cluster state to be \"available\": %s", err) 460 } 461 462 return resourceAwsRDSClusterRead(d, meta) 463 } 464 465 func resourceAwsRDSClusterRead(d *schema.ResourceData, meta interface{}) error { 466 conn := meta.(*AWSClient).rdsconn 467 468 resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{ 469 DBClusterIdentifier: aws.String(d.Id()), 470 }) 471 472 if err != nil { 473 if awsErr, ok := err.(awserr.Error); ok { 474 if "DBClusterNotFoundFault" == awsErr.Code() { 475 d.SetId("") 476 log.Printf("[DEBUG] RDS Cluster (%s) not found", d.Id()) 477 return nil 478 } 479 } 480 log.Printf("[DEBUG] Error describing RDS Cluster (%s)", d.Id()) 481 return err 482 } 483 484 var dbc *rds.DBCluster 485 for _, c := range resp.DBClusters { 486 if *c.DBClusterIdentifier == d.Id() { 487 dbc = c 488 } 489 } 490 491 if dbc == nil { 492 log.Printf("[WARN] RDS Cluster (%s) not found", d.Id()) 493 d.SetId("") 494 return nil 495 } 496 497 if err := d.Set("availability_zones", aws.StringValueSlice(dbc.AvailabilityZones)); err != nil { 498 return fmt.Errorf("[DEBUG] Error saving AvailabilityZones to state for RDS Cluster (%s): %s", d.Id(), err) 499 } 500 501 // Only set the DatabaseName if it is not nil. There is a known API bug where 502 // RDS accepts a DatabaseName but does not return it, causing a perpetual 503 // diff. 504 // See https://github.com/hashicorp/terraform/issues/4671 for backstory 505 if dbc.DatabaseName != nil { 506 d.Set("database_name", dbc.DatabaseName) 507 } 508 509 d.Set("cluster_identifier", dbc.DBClusterIdentifier) 510 d.Set("db_subnet_group_name", dbc.DBSubnetGroup) 511 d.Set("db_cluster_parameter_group_name", dbc.DBClusterParameterGroup) 512 d.Set("endpoint", dbc.Endpoint) 513 d.Set("engine", dbc.Engine) 514 d.Set("master_username", dbc.MasterUsername) 515 d.Set("port", dbc.Port) 516 d.Set("storage_encrypted", dbc.StorageEncrypted) 517 d.Set("backup_retention_period", dbc.BackupRetentionPeriod) 518 d.Set("preferred_backup_window", dbc.PreferredBackupWindow) 519 d.Set("preferred_maintenance_window", dbc.PreferredMaintenanceWindow) 520 d.Set("kms_key_id", dbc.KmsKeyId) 521 d.Set("reader_endpoint", dbc.ReaderEndpoint) 522 d.Set("replication_source_identifier", dbc.ReplicationSourceIdentifier) 523 524 var vpcg []string 525 for _, g := range dbc.VpcSecurityGroups { 526 vpcg = append(vpcg, *g.VpcSecurityGroupId) 527 } 528 if err := d.Set("vpc_security_group_ids", vpcg); err != nil { 529 return fmt.Errorf("[DEBUG] Error saving VPC Security Group IDs to state for RDS Cluster (%s): %s", d.Id(), err) 530 } 531 532 var cm []string 533 for _, m := range dbc.DBClusterMembers { 534 cm = append(cm, *m.DBInstanceIdentifier) 535 } 536 if err := d.Set("cluster_members", cm); err != nil { 537 return fmt.Errorf("[DEBUG] Error saving RDS Cluster Members to state for RDS Cluster (%s): %s", d.Id(), err) 538 } 539 540 // Fetch and save tags 541 arn, err := buildRDSClusterARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region) 542 if err != nil { 543 log.Printf("[DEBUG] Error building ARN for RDS Cluster (%s), not setting Tags", *dbc.DBClusterIdentifier) 544 } else { 545 if err := saveTagsRDS(conn, d, arn); err != nil { 546 log.Printf("[WARN] Failed to save tags for RDS Cluster (%s): %s", *dbc.DBClusterIdentifier, err) 547 } 548 } 549 550 return nil 551 } 552 553 func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error { 554 conn := meta.(*AWSClient).rdsconn 555 requestUpdate := false 556 557 req := &rds.ModifyDBClusterInput{ 558 ApplyImmediately: aws.Bool(d.Get("apply_immediately").(bool)), 559 DBClusterIdentifier: aws.String(d.Id()), 560 } 561 562 if d.HasChange("master_password") { 563 req.MasterUserPassword = aws.String(d.Get("master_password").(string)) 564 requestUpdate = true 565 } 566 567 if d.HasChange("vpc_security_group_ids") { 568 if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { 569 req.VpcSecurityGroupIds = expandStringList(attr.List()) 570 } else { 571 req.VpcSecurityGroupIds = []*string{} 572 } 573 requestUpdate = true 574 } 575 576 if d.HasChange("preferred_backup_window") { 577 req.PreferredBackupWindow = aws.String(d.Get("preferred_backup_window").(string)) 578 requestUpdate = true 579 } 580 581 if d.HasChange("preferred_maintenance_window") { 582 req.PreferredMaintenanceWindow = aws.String(d.Get("preferred_maintenance_window").(string)) 583 requestUpdate = true 584 } 585 586 if d.HasChange("backup_retention_period") { 587 req.BackupRetentionPeriod = aws.Int64(int64(d.Get("backup_retention_period").(int))) 588 requestUpdate = true 589 } 590 591 if d.HasChange("db_cluster_parameter_group_name") { 592 d.SetPartial("db_cluster_parameter_group_name") 593 req.DBClusterParameterGroupName = aws.String(d.Get("db_cluster_parameter_group_name").(string)) 594 requestUpdate = true 595 } 596 597 if requestUpdate { 598 _, err := conn.ModifyDBCluster(req) 599 if err != nil { 600 return fmt.Errorf("[WARN] Error modifying RDS Cluster (%s): %s", d.Id(), err) 601 } 602 } 603 604 if arn, err := buildRDSClusterARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region); err == nil { 605 if err := setTagsRDS(conn, d, arn); err != nil { 606 return err 607 } else { 608 d.SetPartial("tags") 609 } 610 } 611 612 return resourceAwsRDSClusterRead(d, meta) 613 } 614 615 func resourceAwsRDSClusterDelete(d *schema.ResourceData, meta interface{}) error { 616 conn := meta.(*AWSClient).rdsconn 617 log.Printf("[DEBUG] Destroying RDS Cluster (%s)", d.Id()) 618 619 deleteOpts := rds.DeleteDBClusterInput{ 620 DBClusterIdentifier: aws.String(d.Id()), 621 } 622 623 skipFinalSnapshot := d.Get("skip_final_snapshot").(bool) 624 deleteOpts.SkipFinalSnapshot = aws.Bool(skipFinalSnapshot) 625 626 if skipFinalSnapshot == false { 627 if name, present := d.GetOk("final_snapshot_identifier"); present { 628 deleteOpts.FinalDBSnapshotIdentifier = aws.String(name.(string)) 629 } else { 630 return fmt.Errorf("RDS Cluster FinalSnapshotIdentifier is required when a final snapshot is required") 631 } 632 } 633 634 log.Printf("[DEBUG] RDS Cluster delete options: %s", deleteOpts) 635 _, err := conn.DeleteDBCluster(&deleteOpts) 636 if err != nil { 637 if awsErr, ok := err.(awserr.Error); ok { 638 if "InvalidDBClusterStateFault" == awsErr.Code() { 639 return fmt.Errorf("RDS Cluster cannot be deleted: %s", awsErr.Message()) 640 } 641 } 642 } 643 644 stateConf := &resource.StateChangeConf{ 645 Pending: []string{"available", "deleting", "backing-up", "modifying"}, 646 Target: []string{"destroyed"}, 647 Refresh: resourceAwsRDSClusterStateRefreshFunc(d, meta), 648 Timeout: 15 * time.Minute, 649 MinTimeout: 3 * time.Second, 650 } 651 652 // Wait, catching any errors 653 _, err = stateConf.WaitForState() 654 if err != nil { 655 return fmt.Errorf("[WARN] Error deleting RDS Cluster (%s): %s", d.Id(), err) 656 } 657 658 return nil 659 } 660 661 func resourceAwsRDSClusterStateRefreshFunc( 662 d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc { 663 return func() (interface{}, string, error) { 664 conn := meta.(*AWSClient).rdsconn 665 666 resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{ 667 DBClusterIdentifier: aws.String(d.Id()), 668 }) 669 670 if err != nil { 671 if awsErr, ok := err.(awserr.Error); ok { 672 if "DBClusterNotFoundFault" == awsErr.Code() { 673 return 42, "destroyed", nil 674 } 675 } 676 log.Printf("[WARN] Error on retrieving DB Cluster (%s) when waiting: %s", d.Id(), err) 677 return nil, "", err 678 } 679 680 var dbc *rds.DBCluster 681 682 for _, c := range resp.DBClusters { 683 if *c.DBClusterIdentifier == d.Id() { 684 dbc = c 685 } 686 } 687 688 if dbc == nil { 689 return 42, "destroyed", nil 690 } 691 692 if dbc.Status != nil { 693 log.Printf("[DEBUG] DB Cluster status (%s): %s", d.Id(), *dbc.Status) 694 } 695 696 return dbc, *dbc.Status, nil 697 } 698 } 699 700 func buildRDSClusterARN(identifier, partition, accountid, region string) (string, error) { 701 if partition == "" { 702 return "", fmt.Errorf("Unable to construct RDS Cluster ARN because of missing AWS partition") 703 } 704 if accountid == "" { 705 return "", fmt.Errorf("Unable to construct RDS Cluster ARN because of missing AWS Account ID") 706 } 707 708 arn := fmt.Sprintf("arn:%s:rds:%s:%s:cluster:%s", partition, region, accountid, identifier) 709 return arn, nil 710 711 }