github.com/arvindram03/terraform@v0.3.7-0.20150212015210-408f838db36d/builtin/providers/aws/resource_aws_db_instance.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/hashcode"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  	"github.com/mitchellh/goamz/rds"
    13  )
    14  
    15  func resourceAwsDbInstance() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceAwsDbInstanceCreate,
    18  		Read:   resourceAwsDbInstanceRead,
    19  		Delete: resourceAwsDbInstanceDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Optional: true,
    25  				ForceNew: true,
    26  			},
    27  
    28  			"username": &schema.Schema{
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  
    34  			"password": &schema.Schema{
    35  				Type:     schema.TypeString,
    36  				Required: true,
    37  				ForceNew: true,
    38  			},
    39  
    40  			"engine": &schema.Schema{
    41  				Type:     schema.TypeString,
    42  				Required: true,
    43  				ForceNew: true,
    44  			},
    45  
    46  			"engine_version": &schema.Schema{
    47  				Type:     schema.TypeString,
    48  				Required: true,
    49  				ForceNew: true,
    50  			},
    51  
    52  			"allocated_storage": &schema.Schema{
    53  				Type:     schema.TypeInt,
    54  				Required: true,
    55  				ForceNew: true,
    56  			},
    57  
    58  			"identifier": &schema.Schema{
    59  				Type:     schema.TypeString,
    60  				Required: true,
    61  				ForceNew: true,
    62  			},
    63  
    64  			"instance_class": &schema.Schema{
    65  				Type:     schema.TypeString,
    66  				Required: true,
    67  				ForceNew: true,
    68  			},
    69  
    70  			"availability_zone": &schema.Schema{
    71  				Type:     schema.TypeString,
    72  				Optional: true,
    73  				Computed: true,
    74  				ForceNew: true,
    75  			},
    76  
    77  			"backup_retention_period": &schema.Schema{
    78  				Type:     schema.TypeInt,
    79  				Optional: true,
    80  				Computed: true,
    81  				ForceNew: true,
    82  			},
    83  
    84  			"backup_window": &schema.Schema{
    85  				Type:     schema.TypeString,
    86  				Optional: true,
    87  				Computed: true,
    88  				ForceNew: true,
    89  			},
    90  
    91  			"iops": &schema.Schema{
    92  				Type:     schema.TypeInt,
    93  				Optional: true,
    94  				ForceNew: true,
    95  			},
    96  
    97  			"maintenance_window": &schema.Schema{
    98  				Type:     schema.TypeString,
    99  				Optional: true,
   100  				Computed: true,
   101  				ForceNew: true,
   102  			},
   103  
   104  			"multi_az": &schema.Schema{
   105  				Type:     schema.TypeBool,
   106  				Optional: true,
   107  				Computed: true,
   108  				ForceNew: true,
   109  			},
   110  
   111  			"port": &schema.Schema{
   112  				Type:     schema.TypeInt,
   113  				Optional: true,
   114  				Computed: true,
   115  				ForceNew: true,
   116  			},
   117  
   118  			"publicly_accessible": &schema.Schema{
   119  				Type:     schema.TypeBool,
   120  				Optional: true,
   121  				ForceNew: true,
   122  			},
   123  
   124  			"vpc_security_group_ids": &schema.Schema{
   125  				Type:     schema.TypeSet,
   126  				Optional: true,
   127  				Elem:     &schema.Schema{Type: schema.TypeString},
   128  				Set: func(v interface{}) int {
   129  					return hashcode.String(v.(string))
   130  				},
   131  			},
   132  
   133  			"security_group_names": &schema.Schema{
   134  				Type:     schema.TypeSet,
   135  				Optional: true,
   136  				Elem:     &schema.Schema{Type: schema.TypeString},
   137  				Set: func(v interface{}) int {
   138  					return hashcode.String(v.(string))
   139  				},
   140  			},
   141  
   142  			"final_snapshot_identifier": &schema.Schema{
   143  				Type:     schema.TypeString,
   144  				Optional: true,
   145  				ForceNew: true,
   146  			},
   147  
   148  			"db_subnet_group_name": &schema.Schema{
   149  				Type:     schema.TypeString,
   150  				Optional: true,
   151  				ForceNew: true,
   152  			},
   153  
   154  			"parameter_group_name": &schema.Schema{
   155  				Type:     schema.TypeString,
   156  				Optional: true,
   157  				Computed: true,
   158  				ForceNew: true,
   159  			},
   160  
   161  			"address": &schema.Schema{
   162  				Type:     schema.TypeString,
   163  				Computed: true,
   164  			},
   165  
   166  			"endpoint": &schema.Schema{
   167  				Type:     schema.TypeString,
   168  				Computed: true,
   169  			},
   170  
   171  			"status": &schema.Schema{
   172  				Type:     schema.TypeString,
   173  				Computed: true,
   174  			},
   175  		},
   176  	}
   177  }
   178  
   179  func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error {
   180  	conn := meta.(*AWSClient).rdsconn
   181  	opts := rds.CreateDBInstance{
   182  		AllocatedStorage:     d.Get("allocated_storage").(int),
   183  		SetAllocatedStorage:  true,
   184  		DBInstanceClass:      d.Get("instance_class").(string),
   185  		DBInstanceIdentifier: d.Get("identifier").(string),
   186  		DBName:               d.Get("name").(string),
   187  		MasterUsername:       d.Get("username").(string),
   188  		MasterUserPassword:   d.Get("password").(string),
   189  		Engine:               d.Get("engine").(string),
   190  		EngineVersion:        d.Get("engine_version").(string),
   191  	}
   192  
   193  	if attr, ok := d.GetOk("backup_retention_period"); ok {
   194  		opts.BackupRetentionPeriod = attr.(int)
   195  		opts.SetBackupRetentionPeriod = true
   196  	}
   197  
   198  	if attr, ok := d.GetOk("iops"); ok {
   199  		opts.Iops = attr.(int)
   200  		opts.SetIops = true
   201  	}
   202  
   203  	if attr, ok := d.GetOk("port"); ok {
   204  		opts.Port = attr.(int)
   205  		opts.SetPort = true
   206  	}
   207  
   208  	if attr, ok := d.GetOk("multi_az"); ok {
   209  		opts.MultiAZ = attr.(bool)
   210  	}
   211  
   212  	if attr, ok := d.GetOk("availability_zone"); ok {
   213  		opts.AvailabilityZone = attr.(string)
   214  	}
   215  
   216  	if attr, ok := d.GetOk("maintenance_window"); ok {
   217  		opts.PreferredMaintenanceWindow = attr.(string)
   218  	}
   219  
   220  	if attr, ok := d.GetOk("backup_window"); ok {
   221  		opts.PreferredBackupWindow = attr.(string)
   222  	}
   223  
   224  	if attr, ok := d.GetOk("publicly_accessible"); ok {
   225  		opts.PubliclyAccessible = attr.(bool)
   226  	}
   227  
   228  	if attr, ok := d.GetOk("db_subnet_group_name"); ok {
   229  		opts.DBSubnetGroupName = attr.(string)
   230  	}
   231  
   232  	if attr, ok := d.GetOk("parameter_group_name"); ok {
   233  		opts.DBParameterGroupName = attr.(string)
   234  	}
   235  
   236  	if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 {
   237  		var s []string
   238  		for _, v := range attr.List() {
   239  			s = append(s, v.(string))
   240  		}
   241  		opts.VpcSecurityGroupIds = s
   242  	}
   243  
   244  	if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
   245  		var s []string
   246  		for _, v := range attr.List() {
   247  			s = append(s, v.(string))
   248  		}
   249  		opts.DBSecurityGroupNames = s
   250  	}
   251  
   252  	log.Printf("[DEBUG] DB Instance create configuration: %#v", opts)
   253  	_, err := conn.CreateDBInstance(&opts)
   254  	if err != nil {
   255  		return fmt.Errorf("Error creating DB Instance: %s", err)
   256  	}
   257  
   258  	d.SetId(d.Get("identifier").(string))
   259  
   260  	log.Printf("[INFO] DB Instance ID: %s", d.Id())
   261  
   262  	log.Println(
   263  		"[INFO] Waiting for DB Instance to be available")
   264  
   265  	stateConf := &resource.StateChangeConf{
   266  		Pending:    []string{"creating", "backing-up", "modifying"},
   267  		Target:     "available",
   268  		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   269  		Timeout:    20 * time.Minute,
   270  		MinTimeout: 10 * time.Second,
   271  		Delay:      30 * time.Second, // Wait 30 secs before starting
   272  	}
   273  
   274  	// Wait, catching any errors
   275  	_, err = stateConf.WaitForState()
   276  	if err != nil {
   277  		return err
   278  	}
   279  
   280  	return resourceAwsDbInstanceRead(d, meta)
   281  }
   282  
   283  func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error {
   284  	v, err := resourceAwsBbInstanceRetrieve(d, meta)
   285  
   286  	if err != nil {
   287  		return err
   288  	}
   289  	if v == nil {
   290  		d.SetId("")
   291  		return nil
   292  	}
   293  
   294  	d.Set("name", v.DBName)
   295  	d.Set("username", v.MasterUsername)
   296  	d.Set("engine", v.Engine)
   297  	d.Set("engine_version", v.EngineVersion)
   298  	d.Set("allocated_storage", v.AllocatedStorage)
   299  	d.Set("instance_class", v.DBInstanceClass)
   300  	d.Set("availability_zone", v.AvailabilityZone)
   301  	d.Set("backup_retention_period", v.BackupRetentionPeriod)
   302  	d.Set("backup_window", v.PreferredBackupWindow)
   303  	d.Set("maintenance_window", v.PreferredMaintenanceWindow)
   304  	d.Set("multi_az", v.MultiAZ)
   305  	d.Set("port", v.Port)
   306  	d.Set("db_subnet_group_name", v.DBSubnetGroup.Name)
   307  	d.Set("parameter_group_name", v.DBParameterGroupName)
   308  	d.Set("address", v.Address)
   309  	d.Set("endpoint", fmt.Sprintf("%s:%d", v.Address, v.Port))
   310  	d.Set("status", v.DBInstanceStatus)
   311  
   312  	// Create an empty schema.Set to hold all vpc security group ids
   313  	ids := &schema.Set{
   314  		F: func(v interface{}) int {
   315  			return hashcode.String(v.(string))
   316  		},
   317  	}
   318  	for _, v := range v.VpcSecurityGroupIds {
   319  		ids.Add(v)
   320  	}
   321  	d.Set("vpc_security_group_ids", ids)
   322  
   323  	// Create an empty schema.Set to hold all security group names
   324  	sgn := &schema.Set{
   325  		F: func(v interface{}) int {
   326  			return hashcode.String(v.(string))
   327  		},
   328  	}
   329  	for _, v := range v.DBSecurityGroupNames {
   330  		sgn.Add(v)
   331  	}
   332  	d.Set("security_group_names", sgn)
   333  
   334  	return nil
   335  }
   336  
   337  func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error {
   338  	conn := meta.(*AWSClient).rdsconn
   339  
   340  	log.Printf("[DEBUG] DB Instance destroy: %v", d.Id())
   341  
   342  	opts := rds.DeleteDBInstance{DBInstanceIdentifier: d.Id()}
   343  
   344  	finalSnapshot := d.Get("final_snapshot_identifier").(string)
   345  	if finalSnapshot == "" {
   346  		opts.SkipFinalSnapshot = true
   347  	} else {
   348  		opts.FinalDBSnapshotIdentifier = finalSnapshot
   349  	}
   350  
   351  	log.Printf("[DEBUG] DB Instance destroy configuration: %v", opts)
   352  	if _, err := conn.DeleteDBInstance(&opts); err != nil {
   353  		return err
   354  	}
   355  
   356  	log.Println(
   357  		"[INFO] Waiting for DB Instance to be destroyed")
   358  	stateConf := &resource.StateChangeConf{
   359  		Pending: []string{"creating", "backing-up",
   360  			"modifying", "deleting", "available"},
   361  		Target:     "",
   362  		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   363  		Timeout:    20 * time.Minute,
   364  		MinTimeout: 10 * time.Second,
   365  		Delay:      30 * time.Second, // Wait 30 secs before starting
   366  	}
   367  	if _, err := stateConf.WaitForState(); err != nil {
   368  		return err
   369  	}
   370  
   371  	return nil
   372  }
   373  
   374  func resourceAwsBbInstanceRetrieve(
   375  	d *schema.ResourceData, meta interface{}) (*rds.DBInstance, error) {
   376  	conn := meta.(*AWSClient).rdsconn
   377  
   378  	opts := rds.DescribeDBInstances{
   379  		DBInstanceIdentifier: d.Id(),
   380  	}
   381  
   382  	log.Printf("[DEBUG] DB Instance describe configuration: %#v", opts)
   383  
   384  	resp, err := conn.DescribeDBInstances(&opts)
   385  
   386  	if err != nil {
   387  		if strings.Contains(err.Error(), "DBInstanceNotFound") {
   388  			return nil, nil
   389  		}
   390  		return nil, fmt.Errorf("Error retrieving DB Instances: %s", err)
   391  	}
   392  
   393  	if len(resp.DBInstances) != 1 ||
   394  		resp.DBInstances[0].DBInstanceIdentifier != d.Id() {
   395  		if err != nil {
   396  			return nil, nil
   397  		}
   398  	}
   399  
   400  	v := resp.DBInstances[0]
   401  
   402  	return &v, nil
   403  }
   404  
   405  func resourceAwsDbInstanceStateRefreshFunc(
   406  	d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
   407  	return func() (interface{}, string, error) {
   408  		v, err := resourceAwsBbInstanceRetrieve(d, meta)
   409  
   410  		if err != nil {
   411  			log.Printf("Error on retrieving DB Instance when waiting: %s", err)
   412  			return nil, "", err
   413  		}
   414  
   415  		if v == nil {
   416  			return nil, "", nil
   417  		}
   418  
   419  		return v, v.DBInstanceStatus, nil
   420  	}
   421  }