github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/resource_aws_rds_cluster_instance.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/service/rds"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceAwsRDSClusterInstance() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAwsRDSClusterInstanceCreate,
    17  		Read:   resourceAwsRDSClusterInstanceRead,
    18  		Update: resourceAwsRDSClusterInstanceUpdate,
    19  		Delete: resourceAwsRDSClusterInstanceDelete,
    20  		Importer: &schema.ResourceImporter{
    21  			State: schema.ImportStatePassthrough,
    22  		},
    23  
    24  		Schema: map[string]*schema.Schema{
    25  			"identifier": &schema.Schema{
    26  				Type:         schema.TypeString,
    27  				Optional:     true,
    28  				ForceNew:     true,
    29  				ValidateFunc: validateRdsId,
    30  			},
    31  
    32  			"db_subnet_group_name": &schema.Schema{
    33  				Type:     schema.TypeString,
    34  				Optional: true,
    35  				ForceNew: true,
    36  				Computed: true,
    37  			},
    38  
    39  			"writer": &schema.Schema{
    40  				Type:     schema.TypeBool,
    41  				Computed: true,
    42  			},
    43  
    44  			"cluster_identifier": &schema.Schema{
    45  				Type:     schema.TypeString,
    46  				Required: true,
    47  				ForceNew: true,
    48  			},
    49  
    50  			"endpoint": &schema.Schema{
    51  				Type:     schema.TypeString,
    52  				Computed: true,
    53  			},
    54  
    55  			"port": &schema.Schema{
    56  				Type:     schema.TypeInt,
    57  				Computed: true,
    58  			},
    59  
    60  			"publicly_accessible": &schema.Schema{
    61  				Type:     schema.TypeBool,
    62  				Optional: true,
    63  				Default:  false,
    64  			},
    65  
    66  			"instance_class": &schema.Schema{
    67  				Type:     schema.TypeString,
    68  				Required: true,
    69  			},
    70  
    71  			"db_parameter_group_name": &schema.Schema{
    72  				Type:     schema.TypeString,
    73  				Optional: true,
    74  				Computed: true,
    75  			},
    76  
    77  			// apply_immediately is used to determine when the update modifications
    78  			// take place.
    79  			// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html
    80  			"apply_immediately": &schema.Schema{
    81  				Type:     schema.TypeBool,
    82  				Optional: true,
    83  				Computed: true,
    84  			},
    85  
    86  			"kms_key_id": &schema.Schema{
    87  				Type:     schema.TypeString,
    88  				Optional: true,
    89  				Computed: true,
    90  				ForceNew: true,
    91  			},
    92  
    93  			"storage_encrypted": &schema.Schema{
    94  				Type:     schema.TypeBool,
    95  				Optional: true,
    96  				Default:  false,
    97  				ForceNew: true,
    98  			},
    99  
   100  			"monitoring_role_arn": &schema.Schema{
   101  				Type:     schema.TypeString,
   102  				Optional: true,
   103  				Computed: true,
   104  			},
   105  
   106  			"monitoring_interval": &schema.Schema{
   107  				Type:     schema.TypeInt,
   108  				Optional: true,
   109  				Default:  0,
   110  			},
   111  
   112  			"promotion_tier": &schema.Schema{
   113  				Type:     schema.TypeInt,
   114  				Optional: true,
   115  				Default:  0,
   116  			},
   117  
   118  			"tags": tagsSchema(),
   119  		},
   120  	}
   121  }
   122  
   123  func resourceAwsRDSClusterInstanceCreate(d *schema.ResourceData, meta interface{}) error {
   124  	conn := meta.(*AWSClient).rdsconn
   125  	tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
   126  
   127  	createOpts := &rds.CreateDBInstanceInput{
   128  		DBInstanceClass:     aws.String(d.Get("instance_class").(string)),
   129  		DBClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)),
   130  		Engine:              aws.String("aurora"),
   131  		PubliclyAccessible:  aws.Bool(d.Get("publicly_accessible").(bool)),
   132  		PromotionTier:       aws.Int64(int64(d.Get("promotion_tier").(int))),
   133  		Tags:                tags,
   134  	}
   135  
   136  	if attr, ok := d.GetOk("db_parameter_group_name"); ok {
   137  		createOpts.DBParameterGroupName = aws.String(attr.(string))
   138  	}
   139  
   140  	if v := d.Get("identifier").(string); v != "" {
   141  		createOpts.DBInstanceIdentifier = aws.String(v)
   142  	} else {
   143  		createOpts.DBInstanceIdentifier = aws.String(resource.UniqueId())
   144  	}
   145  
   146  	if attr, ok := d.GetOk("db_subnet_group_name"); ok {
   147  		createOpts.DBSubnetGroupName = aws.String(attr.(string))
   148  	}
   149  
   150  	if attr, ok := d.GetOk("monitoring_role_arn"); ok {
   151  		createOpts.MonitoringRoleArn = aws.String(attr.(string))
   152  	}
   153  
   154  	if attr, ok := d.GetOk("monitoring_interval"); ok {
   155  		createOpts.MonitoringInterval = aws.Int64(int64(attr.(int)))
   156  	}
   157  
   158  	log.Printf("[DEBUG] Creating RDS DB Instance opts: %s", createOpts)
   159  	resp, err := conn.CreateDBInstance(createOpts)
   160  	if err != nil {
   161  		return err
   162  	}
   163  
   164  	d.SetId(*resp.DBInstance.DBInstanceIdentifier)
   165  
   166  	// reuse db_instance refresh func
   167  	stateConf := &resource.StateChangeConf{
   168  		Pending:    []string{"creating", "backing-up", "modifying"},
   169  		Target:     []string{"available"},
   170  		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   171  		Timeout:    40 * time.Minute,
   172  		MinTimeout: 10 * time.Second,
   173  		Delay:      10 * time.Second,
   174  	}
   175  
   176  	// Wait, catching any errors
   177  	_, err = stateConf.WaitForState()
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	return resourceAwsRDSClusterInstanceRead(d, meta)
   183  }
   184  
   185  func resourceAwsRDSClusterInstanceRead(d *schema.ResourceData, meta interface{}) error {
   186  	db, err := resourceAwsDbInstanceRetrieve(d, meta)
   187  	// Errors from this helper are always reportable
   188  	if err != nil {
   189  		return fmt.Errorf("[WARN] Error on retrieving RDS Cluster Instance (%s): %s", d.Id(), err)
   190  	}
   191  	// A nil response means "not found"
   192  	if db == nil {
   193  		log.Printf("[WARN] RDS Cluster Instance (%s): not found, removing from state.", d.Id())
   194  		d.SetId("")
   195  		return nil
   196  	}
   197  
   198  	// Retreive DB Cluster information, to determine if this Instance is a writer
   199  	conn := meta.(*AWSClient).rdsconn
   200  	resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{
   201  		DBClusterIdentifier: db.DBClusterIdentifier,
   202  	})
   203  
   204  	var dbc *rds.DBCluster
   205  	for _, c := range resp.DBClusters {
   206  		if *c.DBClusterIdentifier == *db.DBClusterIdentifier {
   207  			dbc = c
   208  		}
   209  	}
   210  
   211  	if dbc == nil {
   212  		return fmt.Errorf("[WARN] Error finding RDS Cluster (%s) for Cluster Instance (%s): %s",
   213  			*db.DBClusterIdentifier, *db.DBInstanceIdentifier, err)
   214  	}
   215  
   216  	for _, m := range dbc.DBClusterMembers {
   217  		if *db.DBInstanceIdentifier == *m.DBInstanceIdentifier {
   218  			if *m.IsClusterWriter == true {
   219  				d.Set("writer", true)
   220  			} else {
   221  				d.Set("writer", false)
   222  			}
   223  		}
   224  	}
   225  
   226  	if db.Endpoint != nil {
   227  		d.Set("endpoint", db.Endpoint.Address)
   228  		d.Set("port", db.Endpoint.Port)
   229  	}
   230  
   231  	d.Set("publicly_accessible", db.PubliclyAccessible)
   232  	d.Set("cluster_identifier", db.DBClusterIdentifier)
   233  	d.Set("instance_class", db.DBInstanceClass)
   234  	d.Set("identifier", db.DBInstanceIdentifier)
   235  	d.Set("storage_encrypted", db.StorageEncrypted)
   236  	d.Set("promotion_tier", db.PromotionTier)
   237  
   238  	if db.MonitoringInterval != nil {
   239  		d.Set("monitoring_interval", db.MonitoringInterval)
   240  	}
   241  
   242  	if db.MonitoringRoleArn != nil {
   243  		d.Set("monitoring_role_arn", db.MonitoringRoleArn)
   244  	}
   245  
   246  	if len(db.DBParameterGroups) > 0 {
   247  		d.Set("db_parameter_group_name", db.DBParameterGroups[0].DBParameterGroupName)
   248  	}
   249  
   250  	// Fetch and save tags
   251  	arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).accountid, meta.(*AWSClient).region)
   252  	if err != nil {
   253  		log.Printf("[DEBUG] Error building ARN for RDS Cluster Instance (%s), not setting Tags", *db.DBInstanceIdentifier)
   254  	} else {
   255  		if err := saveTagsRDS(conn, d, arn); err != nil {
   256  			log.Printf("[WARN] Failed to save tags for RDS Cluster Instance (%s): %s", *db.DBClusterIdentifier, err)
   257  		}
   258  	}
   259  
   260  	return nil
   261  }
   262  
   263  func resourceAwsRDSClusterInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
   264  	conn := meta.(*AWSClient).rdsconn
   265  	requestUpdate := false
   266  
   267  	req := &rds.ModifyDBInstanceInput{
   268  		ApplyImmediately:     aws.Bool(d.Get("apply_immediately").(bool)),
   269  		DBInstanceIdentifier: aws.String(d.Id()),
   270  	}
   271  
   272  	if d.HasChange("db_parameter_group_name") {
   273  		req.DBParameterGroupName = aws.String(d.Get("db_parameter_group_name").(string))
   274  		requestUpdate = true
   275  
   276  	}
   277  
   278  	if d.HasChange("instance_class") {
   279  		req.DBInstanceClass = aws.String(d.Get("instance_class").(string))
   280  		requestUpdate = true
   281  
   282  	}
   283  
   284  	if d.HasChange("monitoring_role_arn") {
   285  		d.SetPartial("monitoring_role_arn")
   286  		req.MonitoringRoleArn = aws.String(d.Get("monitoring_role_arn").(string))
   287  		requestUpdate = true
   288  	}
   289  
   290  	if d.HasChange("monitoring_interval") {
   291  		d.SetPartial("monitoring_interval")
   292  		req.MonitoringInterval = aws.Int64(int64(d.Get("monitoring_interval").(int)))
   293  		requestUpdate = true
   294  	}
   295  
   296  	if d.HasChange("promotion_tier") {
   297  		d.SetPartial("promotion_tier")
   298  		req.PromotionTier = aws.Int64(int64(d.Get("promotion_tier").(int)))
   299  		requestUpdate = true
   300  	}
   301  
   302  	log.Printf("[DEBUG] Send DB Instance Modification request: %#v", requestUpdate)
   303  	if requestUpdate {
   304  		log.Printf("[DEBUG] DB Instance Modification request: %#v", req)
   305  		_, err := conn.ModifyDBInstance(req)
   306  		if err != nil {
   307  			return fmt.Errorf("Error modifying DB Instance %s: %s", d.Id(), err)
   308  		}
   309  
   310  		// reuse db_instance refresh func
   311  		stateConf := &resource.StateChangeConf{
   312  			Pending:    []string{"creating", "backing-up", "modifying"},
   313  			Target:     []string{"available"},
   314  			Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   315  			Timeout:    40 * time.Minute,
   316  			MinTimeout: 10 * time.Second,
   317  			Delay:      10 * time.Second,
   318  		}
   319  
   320  		// Wait, catching any errors
   321  		_, err = stateConf.WaitForState()
   322  		if err != nil {
   323  			return err
   324  		}
   325  
   326  	}
   327  
   328  	if arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).accountid, meta.(*AWSClient).region); err == nil {
   329  		if err := setTagsRDS(conn, d, arn); err != nil {
   330  			return err
   331  		}
   332  	}
   333  
   334  	return resourceAwsRDSClusterInstanceRead(d, meta)
   335  }
   336  
   337  func resourceAwsRDSClusterInstanceDelete(d *schema.ResourceData, meta interface{}) error {
   338  	conn := meta.(*AWSClient).rdsconn
   339  
   340  	log.Printf("[DEBUG] RDS Cluster Instance destroy: %v", d.Id())
   341  
   342  	opts := rds.DeleteDBInstanceInput{DBInstanceIdentifier: aws.String(d.Id())}
   343  
   344  	log.Printf("[DEBUG] RDS Cluster Instance destroy configuration: %s", opts)
   345  	if _, err := conn.DeleteDBInstance(&opts); err != nil {
   346  		return err
   347  	}
   348  
   349  	// re-uses db_instance refresh func
   350  	log.Println("[INFO] Waiting for RDS Cluster Instance to be destroyed")
   351  	stateConf := &resource.StateChangeConf{
   352  		Pending:    []string{"modifying", "deleting"},
   353  		Target:     []string{},
   354  		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
   355  		Timeout:    40 * time.Minute,
   356  		MinTimeout: 10 * time.Second,
   357  	}
   358  
   359  	if _, err := stateConf.WaitForState(); err != nil {
   360  		return err
   361  	}
   362  
   363  	return nil
   364  
   365  }