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