github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/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/rds"
    13  
    14  	"github.com/hashicorp/terraform/helper/resource"
    15  	"github.com/hashicorp/terraform/helper/schema"
    16  )
    17  
    18  func resourceAwsDbInstance() *schema.Resource {
    19  	return &schema.Resource{
    20  		Create: resourceAwsDbInstanceCreate,
    21  		Read:   resourceAwsDbInstanceRead,
    22  		Update: resourceAwsDbInstanceUpdate,
    23  		Delete: resourceAwsDbInstanceDelete,
    24  		Importer: &schema.ResourceImporter{
    25  			State: resourceAwsDbInstanceImport,
    26  		},
    27  
    28  		Schema: map[string]*schema.Schema{
    29  			"name": {
    30  				Type:     schema.TypeString,
    31  				Optional: true,
    32  				Computed: true,
    33  				ForceNew: true,
    34  			},
    35  
    36  			"arn": {
    37  				Type:     schema.TypeString,
    38  				Computed: true,
    39  			},
    40  
    41  			"username": {
    42  				Type:     schema.TypeString,
    43  				Optional: true,
    44  				Computed: true,
    45  				ForceNew: true,
    46  			},
    47  
    48  			"password": {
    49  				Type:      schema.TypeString,
    50  				Optional:  true,
    51  				Sensitive: true,
    52  			},
    53  
    54  			"engine": {
    55  				Type:     schema.TypeString,
    56  				Optional: true,
    57  				Computed: true,
    58  				ForceNew: true,
    59  				StateFunc: func(v interface{}) string {
    60  					value := v.(string)
    61  					return strings.ToLower(value)
    62  				},
    63  			},
    64  
    65  			"engine_version": {
    66  				Type:             schema.TypeString,
    67  				Optional:         true,
    68  				Computed:         true,
    69  				DiffSuppressFunc: suppressAwsDbEngineVersionDiffs,
    70  			},
    71  
    72  			"character_set_name": {
    73  				Type:     schema.TypeString,
    74  				Optional: true,
    75  				Computed: true,
    76  				ForceNew: true,
    77  			},
    78  
    79  			"storage_encrypted": {
    80  				Type:     schema.TypeBool,
    81  				Optional: true,
    82  				ForceNew: true,
    83  			},
    84  
    85  			"allocated_storage": {
    86  				Type:     schema.TypeInt,
    87  				Optional: true,
    88  				Computed: true,
    89  			},
    90  
    91  			"storage_type": {
    92  				Type:     schema.TypeString,
    93  				Optional: true,
    94  				Computed: true,
    95  			},
    96  
    97  			"identifier": {
    98  				Type:         schema.TypeString,
    99  				Optional:     true,
   100  				Computed:     true,
   101  				ForceNew:     true,
   102  				ValidateFunc: validateRdsId,
   103  			},
   104  
   105  			"instance_class": {
   106  				Type:     schema.TypeString,
   107  				Required: true,
   108  			},
   109  
   110  			"availability_zone": {
   111  				Type:     schema.TypeString,
   112  				Optional: true,
   113  				Computed: true,
   114  				ForceNew: true,
   115  			},
   116  
   117  			"backup_retention_period": {
   118  				Type:     schema.TypeInt,
   119  				Optional: true,
   120  				Computed: true,
   121  			},
   122  
   123  			"backup_window": {
   124  				Type:         schema.TypeString,
   125  				Optional:     true,
   126  				Computed:     true,
   127  				ValidateFunc: validateOnceADayWindowFormat,
   128  			},
   129  
   130  			"iops": {
   131  				Type:     schema.TypeInt,
   132  				Optional: true,
   133  			},
   134  
   135  			"license_model": {
   136  				Type:     schema.TypeString,
   137  				Optional: true,
   138  				Computed: true,
   139  			},
   140  
   141  			"maintenance_window": {
   142  				Type:     schema.TypeString,
   143  				Optional: true,
   144  				Computed: true,
   145  				StateFunc: func(v interface{}) string {
   146  					if v != nil {
   147  						value := v.(string)
   148  						return strings.ToLower(value)
   149  					}
   150  					return ""
   151  				},
   152  				ValidateFunc: validateOnceAWeekWindowFormat,
   153  			},
   154  
   155  			"multi_az": {
   156  				Type:     schema.TypeBool,
   157  				Optional: true,
   158  				Computed: true,
   159  			},
   160  
   161  			"port": {
   162  				Type:     schema.TypeInt,
   163  				Optional: true,
   164  				Computed: true,
   165  			},
   166  
   167  			"publicly_accessible": {
   168  				Type:     schema.TypeBool,
   169  				Optional: true,
   170  				Default:  false,
   171  			},
   172  
   173  			"vpc_security_group_ids": {
   174  				Type:     schema.TypeSet,
   175  				Optional: true,
   176  				Computed: true,
   177  				Elem:     &schema.Schema{Type: schema.TypeString},
   178  				Set:      schema.HashString,
   179  			},
   180  
   181  			"security_group_names": {
   182  				Type:     schema.TypeSet,
   183  				Optional: true,
   184  				Elem:     &schema.Schema{Type: schema.TypeString},
   185  				Set:      schema.HashString,
   186  			},
   187  
   188  			"final_snapshot_identifier": {
   189  				Type:     schema.TypeString,
   190  				Optional: true,
   191  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
   192  					value := v.(string)
   193  					if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
   194  						es = append(es, fmt.Errorf(
   195  							"only alphanumeric characters and hyphens allowed in %q", k))
   196  					}
   197  					if regexp.MustCompile(`--`).MatchString(value) {
   198  						es = append(es, fmt.Errorf("%q cannot contain two consecutive hyphens", k))
   199  					}
   200  					if regexp.MustCompile(`-$`).MatchString(value) {
   201  						es = append(es, fmt.Errorf("%q cannot end in a hyphen", k))
   202  					}
   203  					return
   204  				},
   205  			},
   206  
   207  			"skip_final_snapshot": {
   208  				Type:     schema.TypeBool,
   209  				Optional: true,
   210  				Default:  false,
   211  			},
   212  
   213  			"copy_tags_to_snapshot": {
   214  				Type:     schema.TypeBool,
   215  				Optional: true,
   216  				Default:  false,
   217  			},
   218  
   219  			"db_subnet_group_name": {
   220  				Type:     schema.TypeString,
   221  				Optional: true,
   222  				Computed: true,
   223  			},
   224  
   225  			"parameter_group_name": {
   226  				Type:     schema.TypeString,
   227  				Optional: true,
   228  				Computed: true,
   229  			},
   230  
   231  			"address": {
   232  				Type:     schema.TypeString,
   233  				Computed: true,
   234  			},
   235  
   236  			"endpoint": {
   237  				Type:     schema.TypeString,
   238  				Computed: true,
   239  			},
   240  
   241  			"hosted_zone_id": {
   242  				Type:     schema.TypeString,
   243  				Computed: true,
   244  			},
   245  
   246  			"status": {
   247  				Type:     schema.TypeString,
   248  				Computed: true,
   249  			},
   250  
   251  			// apply_immediately is used to determine when the update modifications
   252  			// take place.
   253  			// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html
   254  			"apply_immediately": {
   255  				Type:     schema.TypeBool,
   256  				Optional: true,
   257  				Computed: true,
   258  			},
   259  
   260  			"replicate_source_db": {
   261  				Type:     schema.TypeString,
   262  				Optional: true,
   263  			},
   264  
   265  			"replicas": {
   266  				Type:     schema.TypeList,
   267  				Computed: true,
   268  				Elem:     &schema.Schema{Type: schema.TypeString},
   269  			},
   270  
   271  			"snapshot_identifier": {
   272  				Type:     schema.TypeString,
   273  				Computed: false,
   274  				Optional: true,
   275  				ForceNew: true,
   276  				Elem:     &schema.Schema{Type: schema.TypeString},
   277  			},
   278  
   279  			"auto_minor_version_upgrade": {
   280  				Type:     schema.TypeBool,
   281  				Optional: true,
   282  				Default:  true,
   283  			},
   284  
   285  			"allow_major_version_upgrade": {
   286  				Type:     schema.TypeBool,
   287  				Computed: false,
   288  				Optional: true,
   289  			},
   290  
   291  			"monitoring_role_arn": {
   292  				Type:     schema.TypeString,
   293  				Optional: true,
   294  				Computed: true,
   295  			},
   296  
   297  			"monitoring_interval": {
   298  				Type:     schema.TypeInt,
   299  				Optional: true,
   300  				Default:  0,
   301  			},
   302  
   303  			"option_group_name": {
   304  				Type:     schema.TypeString,
   305  				Optional: true,
   306  				Computed: true,
   307  			},
   308  
   309  			"kms_key_id": {
   310  				Type:         schema.TypeString,
   311  				Optional:     true,
   312  				Computed:     true,
   313  				ForceNew:     true,
   314  				ValidateFunc: validateArn,
   315  			},
   316  
   317  			"timezone": {
   318  				Type:     schema.TypeString,
   319  				Optional: true,
   320  				Computed: true,
   321  				ForceNew: true,
   322  			},
   323  
   324  			"tags": tagsSchema(),
   325  		},
   326  	}
   327  }
   328  
   329  func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error {
   330  	conn := meta.(*AWSClient).rdsconn
   331  	tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
   332  
   333  	identifier := d.Get("identifier").(string)
   334  	// Generate a unique ID for the user
   335  	if identifier == "" {
   336  		identifier = resource.PrefixedUniqueId("tf-")
   337  		// SQL Server identifier size is max 15 chars, so truncate
   338  		if engine := d.Get("engine").(string); engine != "" {
   339  			if strings.Contains(strings.ToLower(engine), "sqlserver") {
   340  				identifier = identifier[:15]
   341  			}
   342  		}
   343  		d.Set("identifier", identifier)
   344  	}
   345  
   346  	if v, ok := d.GetOk("replicate_source_db"); ok {
   347  		opts := rds.CreateDBInstanceReadReplicaInput{
   348  			SourceDBInstanceIdentifier: aws.String(v.(string)),
   349  			CopyTagsToSnapshot:         aws.Bool(d.Get("copy_tags_to_snapshot").(bool)),
   350  			DBInstanceClass:            aws.String(d.Get("instance_class").(string)),
   351  			DBInstanceIdentifier:       aws.String(identifier),
   352  			PubliclyAccessible:         aws.Bool(d.Get("publicly_accessible").(bool)),
   353  			Tags:                       tags,
   354  		}
   355  		if attr, ok := d.GetOk("iops"); ok {
   356  			opts.Iops = aws.Int64(int64(attr.(int)))
   357  		}
   358  
   359  		if attr, ok := d.GetOk("port"); ok {
   360  			opts.Port = aws.Int64(int64(attr.(int)))
   361  		}
   362  
   363  		if attr, ok := d.GetOk("availability_zone"); ok {
   364  			opts.AvailabilityZone = aws.String(attr.(string))
   365  		}
   366  
   367  		if attr, ok := d.GetOk("storage_type"); ok {
   368  			opts.StorageType = aws.String(attr.(string))
   369  		}
   370  
   371  		if attr, ok := d.GetOk("db_subnet_group_name"); ok {
   372  			opts.DBSubnetGroupName = aws.String(attr.(string))
   373  		}
   374  
   375  		if attr, ok := d.GetOk("monitoring_role_arn"); ok {
   376  			opts.MonitoringRoleArn = aws.String(attr.(string))
   377  		}
   378  
   379  		if attr, ok := d.GetOk("monitoring_interval"); ok {
   380  			opts.MonitoringInterval = aws.Int64(int64(attr.(int)))
   381  		}
   382  
   383  		if attr, ok := d.GetOk("option_group_name"); ok {
   384  			opts.OptionGroupName = aws.String(attr.(string))
   385  		}
   386  
   387  		log.Printf("[DEBUG] DB Instance Replica create configuration: %#v", opts)
   388  		_, err := conn.CreateDBInstanceReadReplica(&opts)
   389  		if err != nil {
   390  			return fmt.Errorf("Error creating DB Instance: %s", err)
   391  		}
   392  	} else if _, ok := d.GetOk("snapshot_identifier"); ok {
   393  		opts := rds.RestoreDBInstanceFromDBSnapshotInput{
   394  			DBInstanceClass:         aws.String(d.Get("instance_class").(string)),
   395  			DBInstanceIdentifier:    aws.String(d.Get("identifier").(string)),
   396  			DBSnapshotIdentifier:    aws.String(d.Get("snapshot_identifier").(string)),
   397  			AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
   398  			PubliclyAccessible:      aws.Bool(d.Get("publicly_accessible").(bool)),
   399  			Tags:                    tags,
   400  			CopyTagsToSnapshot:      aws.Bool(d.Get("copy_tags_to_snapshot").(bool)),
   401  		}
   402  
   403  		if attr, ok := d.GetOk("name"); ok {
   404  			opts.DBName = aws.String(attr.(string))
   405  		}
   406  
   407  		if attr, ok := d.GetOk("availability_zone"); ok {
   408  			opts.AvailabilityZone = aws.String(attr.(string))
   409  		}
   410  
   411  		if attr, ok := d.GetOk("db_subnet_group_name"); ok {
   412  			opts.DBSubnetGroupName = aws.String(attr.(string))
   413  		}
   414  
   415  		if attr, ok := d.GetOk("engine"); ok {
   416  			opts.Engine = aws.String(attr.(string))
   417  		}
   418  
   419  		if attr, ok := d.GetOk("iops"); ok {
   420  			opts.Iops = aws.Int64(int64(attr.(int)))
   421  		}
   422  
   423  		if attr, ok := d.GetOk("license_model"); ok {
   424  			opts.LicenseModel = aws.String(attr.(string))
   425  		}
   426  
   427  		if attr, ok := d.GetOk("multi_az"); ok {
   428  			opts.MultiAZ = aws.Bool(attr.(bool))
   429  		}
   430  
   431  		if attr, ok := d.GetOk("option_group_name"); ok {
   432  			opts.OptionGroupName = aws.String(attr.(string))
   433  
   434  		}
   435  
   436  		if attr, ok := d.GetOk("port"); ok {
   437  			opts.Port = aws.Int64(int64(attr.(int)))
   438  		}
   439  
   440  		if attr, ok := d.GetOk("tde_credential_arn"); ok {
   441  			opts.TdeCredentialArn = aws.String(attr.(string))
   442  		}
   443  
   444  		if attr, ok := d.GetOk("storage_type"); ok {
   445  			opts.StorageType = aws.String(attr.(string))
   446  		}
   447  
   448  		log.Printf("[DEBUG] DB Instance restore from snapshot configuration: %s", opts)
   449  		_, err := conn.RestoreDBInstanceFromDBSnapshot(&opts)
   450  		if err != nil {
   451  			return fmt.Errorf("Error creating DB Instance: %s", err)
   452  		}
   453  
   454  		var sgUpdate bool
   455  		var passwordUpdate bool
   456  
   457  		if _, ok := d.GetOk("password"); ok {
   458  			passwordUpdate = true
   459  		}
   460  
   461  		if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 {
   462  			sgUpdate = true
   463  		}
   464  		if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
   465  			sgUpdate = true
   466  		}
   467  		if sgUpdate || passwordUpdate {
   468  			log.Printf("[INFO] DB is restoring from snapshot with default security, but custom security should be set, will now update after snapshot is restored!")
   469  
   470  			// wait for instance to get up and then modify security
   471  			d.SetId(d.Get("identifier").(string))
   472  
   473  			log.Printf("[INFO] DB Instance ID: %s", d.Id())
   474  
   475  			log.Println(
   476  				"[INFO] Waiting for DB Instance to be available")
   477  
   478  			stateConf := &resource.StateChangeConf{
   479  				Pending: []string{"creating", "backing-up", "modifying", "resetting-master-credentials",
   480  					"maintenance", "renaming", "rebooting", "upgrading"},
   481  				Target:     []string{"available"},
   482  				Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   483  				Timeout:    40 * time.Minute,
   484  				MinTimeout: 10 * time.Second,
   485  				Delay:      30 * time.Second, // Wait 30 secs before starting
   486  			}
   487  
   488  			// Wait, catching any errors
   489  			_, err := stateConf.WaitForState()
   490  			if err != nil {
   491  				return err
   492  			}
   493  
   494  			err = resourceAwsDbInstanceUpdate(d, meta)
   495  			if err != nil {
   496  				return err
   497  			}
   498  
   499  		}
   500  	} else {
   501  		if _, ok := d.GetOk("allocated_storage"); !ok {
   502  			return fmt.Errorf(`provider.aws: aws_db_instance: %s: "allocated_storage": required field is not set`, d.Get("name").(string))
   503  		}
   504  		if _, ok := d.GetOk("engine"); !ok {
   505  			return fmt.Errorf(`provider.aws: aws_db_instance: %s: "engine": required field is not set`, d.Get("name").(string))
   506  		}
   507  		if _, ok := d.GetOk("password"); !ok {
   508  			return fmt.Errorf(`provider.aws: aws_db_instance: %s: "password": required field is not set`, d.Get("name").(string))
   509  		}
   510  		if _, ok := d.GetOk("username"); !ok {
   511  			return fmt.Errorf(`provider.aws: aws_db_instance: %s: "username": required field is not set`, d.Get("name").(string))
   512  		}
   513  		opts := rds.CreateDBInstanceInput{
   514  			AllocatedStorage:        aws.Int64(int64(d.Get("allocated_storage").(int))),
   515  			DBName:                  aws.String(d.Get("name").(string)),
   516  			DBInstanceClass:         aws.String(d.Get("instance_class").(string)),
   517  			DBInstanceIdentifier:    aws.String(d.Get("identifier").(string)),
   518  			MasterUsername:          aws.String(d.Get("username").(string)),
   519  			MasterUserPassword:      aws.String(d.Get("password").(string)),
   520  			Engine:                  aws.String(d.Get("engine").(string)),
   521  			EngineVersion:           aws.String(d.Get("engine_version").(string)),
   522  			StorageEncrypted:        aws.Bool(d.Get("storage_encrypted").(bool)),
   523  			AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
   524  			PubliclyAccessible:      aws.Bool(d.Get("publicly_accessible").(bool)),
   525  			Tags:                    tags,
   526  			CopyTagsToSnapshot:      aws.Bool(d.Get("copy_tags_to_snapshot").(bool)),
   527  		}
   528  
   529  		attr := d.Get("backup_retention_period")
   530  		opts.BackupRetentionPeriod = aws.Int64(int64(attr.(int)))
   531  		if attr, ok := d.GetOk("multi_az"); ok {
   532  			opts.MultiAZ = aws.Bool(attr.(bool))
   533  
   534  		}
   535  
   536  		if attr, ok := d.GetOk("character_set_name"); ok {
   537  			opts.CharacterSetName = aws.String(attr.(string))
   538  		}
   539  
   540  		if attr, ok := d.GetOk("timezone"); ok {
   541  			opts.Timezone = aws.String(attr.(string))
   542  		}
   543  
   544  		if attr, ok := d.GetOk("maintenance_window"); ok {
   545  			opts.PreferredMaintenanceWindow = aws.String(attr.(string))
   546  		}
   547  
   548  		if attr, ok := d.GetOk("backup_window"); ok {
   549  			opts.PreferredBackupWindow = aws.String(attr.(string))
   550  		}
   551  
   552  		if attr, ok := d.GetOk("license_model"); ok {
   553  			opts.LicenseModel = aws.String(attr.(string))
   554  		}
   555  		if attr, ok := d.GetOk("parameter_group_name"); ok {
   556  			opts.DBParameterGroupName = aws.String(attr.(string))
   557  		}
   558  
   559  		if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 {
   560  			var s []*string
   561  			for _, v := range attr.List() {
   562  				s = append(s, aws.String(v.(string)))
   563  			}
   564  			opts.VpcSecurityGroupIds = s
   565  		}
   566  
   567  		if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
   568  			var s []*string
   569  			for _, v := range attr.List() {
   570  				s = append(s, aws.String(v.(string)))
   571  			}
   572  			opts.DBSecurityGroups = s
   573  		}
   574  		if attr, ok := d.GetOk("storage_type"); ok {
   575  			opts.StorageType = aws.String(attr.(string))
   576  		}
   577  
   578  		if attr, ok := d.GetOk("db_subnet_group_name"); ok {
   579  			opts.DBSubnetGroupName = aws.String(attr.(string))
   580  		}
   581  
   582  		if attr, ok := d.GetOk("iops"); ok {
   583  			opts.Iops = aws.Int64(int64(attr.(int)))
   584  		}
   585  
   586  		if attr, ok := d.GetOk("port"); ok {
   587  			opts.Port = aws.Int64(int64(attr.(int)))
   588  		}
   589  
   590  		if attr, ok := d.GetOk("availability_zone"); ok {
   591  			opts.AvailabilityZone = aws.String(attr.(string))
   592  		}
   593  
   594  		if attr, ok := d.GetOk("monitoring_role_arn"); ok {
   595  			opts.MonitoringRoleArn = aws.String(attr.(string))
   596  		}
   597  
   598  		if attr, ok := d.GetOk("monitoring_interval"); ok {
   599  			opts.MonitoringInterval = aws.Int64(int64(attr.(int)))
   600  		}
   601  
   602  		if attr, ok := d.GetOk("option_group_name"); ok {
   603  			opts.OptionGroupName = aws.String(attr.(string))
   604  		}
   605  
   606  		if attr, ok := d.GetOk("kms_key_id"); ok {
   607  			opts.KmsKeyId = aws.String(attr.(string))
   608  		}
   609  
   610  		log.Printf("[DEBUG] DB Instance create configuration: %#v", opts)
   611  		var err error
   612  		err = resource.Retry(5*time.Minute, func() *resource.RetryError {
   613  			_, err = conn.CreateDBInstance(&opts)
   614  			if err != nil {
   615  				if awsErr, ok := err.(awserr.Error); ok {
   616  					if awsErr.Code() == "InvalidParameterValue" && strings.Contains(awsErr.Message(), "ENHANCED_MONITORING") {
   617  						return resource.RetryableError(awsErr)
   618  					}
   619  				}
   620  				return resource.NonRetryableError(err)
   621  			}
   622  			return nil
   623  		})
   624  		if err != nil {
   625  			return fmt.Errorf("Error creating DB Instance: %s", err)
   626  		}
   627  	}
   628  
   629  	d.SetId(d.Get("identifier").(string))
   630  
   631  	log.Printf("[INFO] DB Instance ID: %s", d.Id())
   632  
   633  	log.Println(
   634  		"[INFO] Waiting for DB Instance to be available")
   635  
   636  	stateConf := &resource.StateChangeConf{
   637  		Pending: []string{"creating", "backing-up", "modifying", "resetting-master-credentials",
   638  			"maintenance", "renaming", "rebooting", "upgrading", "configuring-enhanced-monitoring"},
   639  		Target:     []string{"available"},
   640  		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   641  		Timeout:    40 * time.Minute,
   642  		MinTimeout: 10 * time.Second,
   643  		Delay:      30 * time.Second, // Wait 30 secs before starting
   644  	}
   645  
   646  	// Wait, catching any errors
   647  	_, err := stateConf.WaitForState()
   648  	if err != nil {
   649  		return err
   650  	}
   651  
   652  	return resourceAwsDbInstanceRead(d, meta)
   653  }
   654  
   655  func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error {
   656  	v, err := resourceAwsDbInstanceRetrieve(d, meta)
   657  
   658  	if err != nil {
   659  		return err
   660  	}
   661  	if v == nil {
   662  		d.SetId("")
   663  		return nil
   664  	}
   665  
   666  	d.Set("name", v.DBName)
   667  	d.Set("identifier", v.DBInstanceIdentifier)
   668  	d.Set("username", v.MasterUsername)
   669  	d.Set("engine", v.Engine)
   670  	d.Set("engine_version", v.EngineVersion)
   671  	d.Set("allocated_storage", v.AllocatedStorage)
   672  	d.Set("iops", v.Iops)
   673  	d.Set("copy_tags_to_snapshot", v.CopyTagsToSnapshot)
   674  	d.Set("auto_minor_version_upgrade", v.AutoMinorVersionUpgrade)
   675  	d.Set("storage_type", v.StorageType)
   676  	d.Set("instance_class", v.DBInstanceClass)
   677  	d.Set("availability_zone", v.AvailabilityZone)
   678  	d.Set("backup_retention_period", v.BackupRetentionPeriod)
   679  	d.Set("backup_window", v.PreferredBackupWindow)
   680  	d.Set("license_model", v.LicenseModel)
   681  	d.Set("maintenance_window", v.PreferredMaintenanceWindow)
   682  	d.Set("publicly_accessible", v.PubliclyAccessible)
   683  	d.Set("multi_az", v.MultiAZ)
   684  	d.Set("kms_key_id", v.KmsKeyId)
   685  	d.Set("port", v.DbInstancePort)
   686  	if v.DBSubnetGroup != nil {
   687  		d.Set("db_subnet_group_name", v.DBSubnetGroup.DBSubnetGroupName)
   688  	}
   689  
   690  	if v.CharacterSetName != nil {
   691  		d.Set("character_set_name", v.CharacterSetName)
   692  	}
   693  
   694  	d.Set("timezone", v.Timezone)
   695  
   696  	if len(v.DBParameterGroups) > 0 {
   697  		d.Set("parameter_group_name", v.DBParameterGroups[0].DBParameterGroupName)
   698  	}
   699  
   700  	if v.Endpoint != nil {
   701  		d.Set("port", v.Endpoint.Port)
   702  		d.Set("address", v.Endpoint.Address)
   703  		d.Set("hosted_zone_id", v.Endpoint.HostedZoneId)
   704  		if v.Endpoint.Address != nil && v.Endpoint.Port != nil {
   705  			d.Set("endpoint",
   706  				fmt.Sprintf("%s:%d", *v.Endpoint.Address, *v.Endpoint.Port))
   707  		}
   708  	}
   709  
   710  	d.Set("status", v.DBInstanceStatus)
   711  	d.Set("storage_encrypted", v.StorageEncrypted)
   712  	if v.OptionGroupMemberships != nil {
   713  		d.Set("option_group_name", v.OptionGroupMemberships[0].OptionGroupName)
   714  	}
   715  
   716  	if v.MonitoringInterval != nil {
   717  		d.Set("monitoring_interval", v.MonitoringInterval)
   718  	}
   719  
   720  	if v.MonitoringRoleArn != nil {
   721  		d.Set("monitoring_role_arn", v.MonitoringRoleArn)
   722  	}
   723  
   724  	// list tags for resource
   725  	// set tags
   726  	conn := meta.(*AWSClient).rdsconn
   727  	arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region)
   728  	if err != nil {
   729  		name := "<empty>"
   730  		if v.DBName != nil && *v.DBName != "" {
   731  			name = *v.DBName
   732  		}
   733  		log.Printf("[DEBUG] Error building ARN for DB Instance, not setting Tags for DB %s", name)
   734  	} else {
   735  		d.Set("arn", arn)
   736  		resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{
   737  			ResourceName: aws.String(arn),
   738  		})
   739  
   740  		if err != nil {
   741  			log.Printf("[DEBUG] Error retrieving tags for ARN: %s", arn)
   742  		}
   743  
   744  		var dt []*rds.Tag
   745  		if len(resp.TagList) > 0 {
   746  			dt = resp.TagList
   747  		}
   748  		d.Set("tags", tagsToMapRDS(dt))
   749  	}
   750  
   751  	// Create an empty schema.Set to hold all vpc security group ids
   752  	ids := &schema.Set{
   753  		F: schema.HashString,
   754  	}
   755  	for _, v := range v.VpcSecurityGroups {
   756  		ids.Add(*v.VpcSecurityGroupId)
   757  	}
   758  	d.Set("vpc_security_group_ids", ids)
   759  
   760  	// Create an empty schema.Set to hold all security group names
   761  	sgn := &schema.Set{
   762  		F: schema.HashString,
   763  	}
   764  	for _, v := range v.DBSecurityGroups {
   765  		sgn.Add(*v.DBSecurityGroupName)
   766  	}
   767  	d.Set("security_group_names", sgn)
   768  
   769  	// replica things
   770  
   771  	var replicas []string
   772  	for _, v := range v.ReadReplicaDBInstanceIdentifiers {
   773  		replicas = append(replicas, *v)
   774  	}
   775  	if err := d.Set("replicas", replicas); err != nil {
   776  		return fmt.Errorf("[DEBUG] Error setting replicas attribute: %#v, error: %#v", replicas, err)
   777  	}
   778  
   779  	d.Set("replicate_source_db", v.ReadReplicaSourceDBInstanceIdentifier)
   780  
   781  	return nil
   782  }
   783  
   784  func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error {
   785  	conn := meta.(*AWSClient).rdsconn
   786  
   787  	log.Printf("[DEBUG] DB Instance destroy: %v", d.Id())
   788  
   789  	opts := rds.DeleteDBInstanceInput{DBInstanceIdentifier: aws.String(d.Id())}
   790  
   791  	skipFinalSnapshot := d.Get("skip_final_snapshot").(bool)
   792  	opts.SkipFinalSnapshot = aws.Bool(skipFinalSnapshot)
   793  
   794  	if skipFinalSnapshot == false {
   795  		if name, present := d.GetOk("final_snapshot_identifier"); present {
   796  			opts.FinalDBSnapshotIdentifier = aws.String(name.(string))
   797  		} else {
   798  			return fmt.Errorf("DB Instance FinalSnapshotIdentifier is required when a final snapshot is required")
   799  		}
   800  	}
   801  
   802  	log.Printf("[DEBUG] DB Instance destroy configuration: %v", opts)
   803  	if _, err := conn.DeleteDBInstance(&opts); err != nil {
   804  		return err
   805  	}
   806  
   807  	log.Println(
   808  		"[INFO] Waiting for DB Instance to be destroyed")
   809  	stateConf := &resource.StateChangeConf{
   810  		Pending: []string{"creating", "backing-up",
   811  			"modifying", "deleting", "available"},
   812  		Target:     []string{},
   813  		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   814  		Timeout:    40 * time.Minute,
   815  		MinTimeout: 10 * time.Second,
   816  		Delay:      30 * time.Second, // Wait 30 secs before starting
   817  	}
   818  	if _, err := stateConf.WaitForState(); err != nil {
   819  		return err
   820  	}
   821  
   822  	return nil
   823  }
   824  
   825  func resourceAwsDbInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
   826  	conn := meta.(*AWSClient).rdsconn
   827  
   828  	d.Partial(true)
   829  
   830  	req := &rds.ModifyDBInstanceInput{
   831  		ApplyImmediately:     aws.Bool(d.Get("apply_immediately").(bool)),
   832  		DBInstanceIdentifier: aws.String(d.Id()),
   833  	}
   834  	d.SetPartial("apply_immediately")
   835  
   836  	requestUpdate := false
   837  	if d.HasChange("allocated_storage") || d.HasChange("iops") {
   838  		d.SetPartial("allocated_storage")
   839  		d.SetPartial("iops")
   840  		req.Iops = aws.Int64(int64(d.Get("iops").(int)))
   841  		req.AllocatedStorage = aws.Int64(int64(d.Get("allocated_storage").(int)))
   842  		requestUpdate = true
   843  	}
   844  	if d.HasChange("allow_major_version_upgrade") {
   845  		d.SetPartial("allow_major_version_upgrade")
   846  		req.AllowMajorVersionUpgrade = aws.Bool(d.Get("allow_major_version_upgrade").(bool))
   847  		requestUpdate = true
   848  	}
   849  	if d.HasChange("backup_retention_period") {
   850  		d.SetPartial("backup_retention_period")
   851  		req.BackupRetentionPeriod = aws.Int64(int64(d.Get("backup_retention_period").(int)))
   852  		requestUpdate = true
   853  	}
   854  	if d.HasChange("copy_tags_to_snapshot") {
   855  		d.SetPartial("copy_tags_to_snapshot")
   856  		req.CopyTagsToSnapshot = aws.Bool(d.Get("copy_tags_to_snapshot").(bool))
   857  		requestUpdate = true
   858  	}
   859  	if d.HasChange("instance_class") {
   860  		d.SetPartial("instance_class")
   861  		req.DBInstanceClass = aws.String(d.Get("instance_class").(string))
   862  		requestUpdate = true
   863  	}
   864  	if d.HasChange("parameter_group_name") {
   865  		d.SetPartial("parameter_group_name")
   866  		req.DBParameterGroupName = aws.String(d.Get("parameter_group_name").(string))
   867  		requestUpdate = true
   868  	}
   869  	if d.HasChange("engine_version") {
   870  		d.SetPartial("engine_version")
   871  		req.EngineVersion = aws.String(d.Get("engine_version").(string))
   872  		req.AllowMajorVersionUpgrade = aws.Bool(d.Get("allow_major_version_upgrade").(bool))
   873  		requestUpdate = true
   874  	}
   875  	if d.HasChange("backup_window") {
   876  		d.SetPartial("backup_window")
   877  		req.PreferredBackupWindow = aws.String(d.Get("backup_window").(string))
   878  		requestUpdate = true
   879  	}
   880  	if d.HasChange("maintenance_window") {
   881  		d.SetPartial("maintenance_window")
   882  		req.PreferredMaintenanceWindow = aws.String(d.Get("maintenance_window").(string))
   883  		requestUpdate = true
   884  	}
   885  	if d.HasChange("password") {
   886  		d.SetPartial("password")
   887  		req.MasterUserPassword = aws.String(d.Get("password").(string))
   888  		requestUpdate = true
   889  	}
   890  	if d.HasChange("multi_az") {
   891  		d.SetPartial("multi_az")
   892  		req.MultiAZ = aws.Bool(d.Get("multi_az").(bool))
   893  		requestUpdate = true
   894  	}
   895  	if d.HasChange("publicly_accessible") {
   896  		d.SetPartial("publicly_accessible")
   897  		req.PubliclyAccessible = aws.Bool(d.Get("publicly_accessible").(bool))
   898  		requestUpdate = true
   899  	}
   900  	if d.HasChange("storage_type") {
   901  		d.SetPartial("storage_type")
   902  		req.StorageType = aws.String(d.Get("storage_type").(string))
   903  		requestUpdate = true
   904  
   905  		if *req.StorageType == "io1" {
   906  			req.Iops = aws.Int64(int64(d.Get("iops").(int)))
   907  		}
   908  	}
   909  	if d.HasChange("auto_minor_version_upgrade") {
   910  		d.SetPartial("auto_minor_version_upgrade")
   911  		req.AutoMinorVersionUpgrade = aws.Bool(d.Get("auto_minor_version_upgrade").(bool))
   912  		requestUpdate = true
   913  	}
   914  
   915  	if d.HasChange("monitoring_role_arn") {
   916  		d.SetPartial("monitoring_role_arn")
   917  		req.MonitoringRoleArn = aws.String(d.Get("monitoring_role_arn").(string))
   918  		requestUpdate = true
   919  	}
   920  
   921  	if d.HasChange("monitoring_interval") {
   922  		d.SetPartial("monitoring_interval")
   923  		req.MonitoringInterval = aws.Int64(int64(d.Get("monitoring_interval").(int)))
   924  		requestUpdate = true
   925  	}
   926  
   927  	if d.HasChange("vpc_security_group_ids") {
   928  		if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 {
   929  			var s []*string
   930  			for _, v := range attr.List() {
   931  				s = append(s, aws.String(v.(string)))
   932  			}
   933  			req.VpcSecurityGroupIds = s
   934  		}
   935  		requestUpdate = true
   936  	}
   937  
   938  	if d.HasChange("security_group_names") {
   939  		if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
   940  			var s []*string
   941  			for _, v := range attr.List() {
   942  				s = append(s, aws.String(v.(string)))
   943  			}
   944  			req.DBSecurityGroups = s
   945  		}
   946  		requestUpdate = true
   947  	}
   948  
   949  	if d.HasChange("option_group_name") {
   950  		d.SetPartial("option_group_name")
   951  		req.OptionGroupName = aws.String(d.Get("option_group_name").(string))
   952  		requestUpdate = true
   953  	}
   954  
   955  	if d.HasChange("port") {
   956  		d.SetPartial("port")
   957  		req.DBPortNumber = aws.Int64(int64(d.Get("port").(int)))
   958  		requestUpdate = true
   959  	}
   960  	if d.HasChange("db_subnet_group_name") && !d.IsNewResource() {
   961  		d.SetPartial("db_subnet_group_name")
   962  		req.DBSubnetGroupName = aws.String(d.Get("db_subnet_group_name").(string))
   963  		requestUpdate = true
   964  	}
   965  
   966  	log.Printf("[DEBUG] Send DB Instance Modification request: %t", requestUpdate)
   967  	if requestUpdate {
   968  		log.Printf("[DEBUG] DB Instance Modification request: %s", req)
   969  		_, err := conn.ModifyDBInstance(req)
   970  		if err != nil {
   971  			return fmt.Errorf("Error modifying DB Instance %s: %s", d.Id(), err)
   972  		}
   973  
   974  		log.Println("[INFO] Waiting for DB Instance to be available")
   975  
   976  		stateConf := &resource.StateChangeConf{
   977  			Pending: []string{"creating", "backing-up", "modifying", "resetting-master-credentials",
   978  				"maintenance", "renaming", "rebooting", "upgrading", "configuring-enhanced-monitoring", "moving-to-vpc"},
   979  			Target:     []string{"available"},
   980  			Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   981  			Timeout:    80 * time.Minute,
   982  			MinTimeout: 10 * time.Second,
   983  			Delay:      30 * time.Second, // Wait 30 secs before starting
   984  		}
   985  
   986  		// Wait, catching any errors
   987  		_, dbStateErr := stateConf.WaitForState()
   988  		if dbStateErr != nil {
   989  			return dbStateErr
   990  		}
   991  	}
   992  
   993  	// separate request to promote a database
   994  	if d.HasChange("replicate_source_db") {
   995  		if d.Get("replicate_source_db").(string) == "" {
   996  			// promote
   997  			opts := rds.PromoteReadReplicaInput{
   998  				DBInstanceIdentifier: aws.String(d.Id()),
   999  			}
  1000  			attr := d.Get("backup_retention_period")
  1001  			opts.BackupRetentionPeriod = aws.Int64(int64(attr.(int)))
  1002  			if attr, ok := d.GetOk("backup_window"); ok {
  1003  				opts.PreferredBackupWindow = aws.String(attr.(string))
  1004  			}
  1005  			_, err := conn.PromoteReadReplica(&opts)
  1006  			if err != nil {
  1007  				return fmt.Errorf("Error promoting database: %#v", err)
  1008  			}
  1009  			d.Set("replicate_source_db", "")
  1010  		} else {
  1011  			return fmt.Errorf("cannot elect new source database for replication")
  1012  		}
  1013  	}
  1014  
  1015  	if arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region); err == nil {
  1016  		if err := setTagsRDS(conn, d, arn); err != nil {
  1017  			return err
  1018  		} else {
  1019  			d.SetPartial("tags")
  1020  		}
  1021  	}
  1022  	d.Partial(false)
  1023  
  1024  	return resourceAwsDbInstanceRead(d, meta)
  1025  }
  1026  
  1027  // resourceAwsDbInstanceRetrieve fetches DBInstance information from the AWS
  1028  // API. It returns an error if there is a communication problem or unexpected
  1029  // error with AWS. When the DBInstance is not found, it returns no error and a
  1030  // nil pointer.
  1031  func resourceAwsDbInstanceRetrieve(
  1032  	d *schema.ResourceData, meta interface{}) (*rds.DBInstance, error) {
  1033  	conn := meta.(*AWSClient).rdsconn
  1034  
  1035  	opts := rds.DescribeDBInstancesInput{
  1036  		DBInstanceIdentifier: aws.String(d.Id()),
  1037  	}
  1038  
  1039  	log.Printf("[DEBUG] DB Instance describe configuration: %#v", opts)
  1040  
  1041  	resp, err := conn.DescribeDBInstances(&opts)
  1042  	if err != nil {
  1043  		dbinstanceerr, ok := err.(awserr.Error)
  1044  		if ok && dbinstanceerr.Code() == "DBInstanceNotFound" {
  1045  			return nil, nil
  1046  		}
  1047  		return nil, fmt.Errorf("Error retrieving DB Instances: %s", err)
  1048  	}
  1049  
  1050  	if len(resp.DBInstances) != 1 ||
  1051  		*resp.DBInstances[0].DBInstanceIdentifier != d.Id() {
  1052  		if err != nil {
  1053  			return nil, nil
  1054  		}
  1055  	}
  1056  
  1057  	return resp.DBInstances[0], nil
  1058  }
  1059  
  1060  func resourceAwsDbInstanceImport(
  1061  	d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
  1062  	// Neither skip_final_snapshot nor final_snapshot_identifier can be fetched
  1063  	// from any API call, so we need to default skip_final_snapshot to true so
  1064  	// that final_snapshot_identifier is not required
  1065  	d.Set("skip_final_snapshot", true)
  1066  	return []*schema.ResourceData{d}, nil
  1067  }
  1068  
  1069  func resourceAwsDbInstanceStateRefreshFunc(
  1070  	d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
  1071  	return func() (interface{}, string, error) {
  1072  		v, err := resourceAwsDbInstanceRetrieve(d, meta)
  1073  
  1074  		if err != nil {
  1075  			log.Printf("Error on retrieving DB Instance when waiting: %s", err)
  1076  			return nil, "", err
  1077  		}
  1078  
  1079  		if v == nil {
  1080  			return nil, "", nil
  1081  		}
  1082  
  1083  		if v.DBInstanceStatus != nil {
  1084  			log.Printf("[DEBUG] DB Instance status for instance %s: %s", d.Id(), *v.DBInstanceStatus)
  1085  		}
  1086  
  1087  		return v, *v.DBInstanceStatus, nil
  1088  	}
  1089  }
  1090  
  1091  func buildRDSARN(identifier, partition, accountid, region string) (string, error) {
  1092  	if partition == "" {
  1093  		return "", fmt.Errorf("Unable to construct RDS ARN because of missing AWS partition")
  1094  	}
  1095  	if accountid == "" {
  1096  		return "", fmt.Errorf("Unable to construct RDS ARN because of missing AWS Account ID")
  1097  	}
  1098  	arn := fmt.Sprintf("arn:%s:rds:%s:%s:db:%s", partition, region, accountid, identifier)
  1099  	return arn, nil
  1100  }