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 }