github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/resource_aws_db_event_subscription.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/aws/awserr" 10 "github.com/aws/aws-sdk-go/service/rds" 11 "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 func resourceAwsDbEventSubscription() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceAwsDbEventSubscriptionCreate, 18 Read: resourceAwsDbEventSubscriptionRead, 19 Update: resourceAwsDbEventSubscriptionUpdate, 20 Delete: resourceAwsDbEventSubscriptionDelete, 21 Schema: map[string]*schema.Schema{ 22 "name": &schema.Schema{ 23 Type: schema.TypeString, 24 Required: true, 25 ForceNew: true, 26 ValidateFunc: validateDbEventSubscriptionName, 27 }, 28 "sns_topic": &schema.Schema{ 29 Type: schema.TypeString, 30 Required: true, 31 }, 32 "event_categories": &schema.Schema{ 33 Type: schema.TypeSet, 34 Optional: true, 35 Elem: &schema.Schema{Type: schema.TypeString}, 36 Set: schema.HashString, 37 }, 38 "source_ids": &schema.Schema{ 39 Type: schema.TypeSet, 40 Optional: true, 41 Elem: &schema.Schema{Type: schema.TypeString}, 42 Set: schema.HashString, 43 // ValidateFunc: validateDbEventSubscriptionSourceIds, 44 // requires source_type to be set, does not seem to be a way to validate this 45 }, 46 "source_type": &schema.Schema{ 47 Type: schema.TypeString, 48 Optional: true, 49 }, 50 "enabled": &schema.Schema{ 51 Type: schema.TypeBool, 52 Optional: true, 53 Default: true, 54 }, 55 "customer_aws_id": &schema.Schema{ 56 Type: schema.TypeString, 57 Computed: true, 58 }, 59 "tags": tagsSchema(), 60 }, 61 } 62 } 63 64 func resourceAwsDbEventSubscriptionCreate(d *schema.ResourceData, meta interface{}) error { 65 rdsconn := meta.(*AWSClient).rdsconn 66 name := d.Get("name").(string) 67 tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) 68 69 sourceIdsSet := d.Get("source_ids").(*schema.Set) 70 sourceIds := make([]*string, sourceIdsSet.Len()) 71 for i, sourceId := range sourceIdsSet.List() { 72 sourceIds[i] = aws.String(sourceId.(string)) 73 } 74 75 eventCategoriesSet := d.Get("event_categories").(*schema.Set) 76 eventCategories := make([]*string, eventCategoriesSet.Len()) 77 for i, eventCategory := range eventCategoriesSet.List() { 78 eventCategories[i] = aws.String(eventCategory.(string)) 79 } 80 81 request := &rds.CreateEventSubscriptionInput{ 82 SubscriptionName: aws.String(name), 83 SnsTopicArn: aws.String(d.Get("sns_topic").(string)), 84 Enabled: aws.Bool(d.Get("enabled").(bool)), 85 SourceIds: sourceIds, 86 SourceType: aws.String(d.Get("source_type").(string)), 87 EventCategories: eventCategories, 88 Tags: tags, 89 } 90 91 log.Println("[DEBUG] Create RDS Event Subscription:", request) 92 93 _, err := rdsconn.CreateEventSubscription(request) 94 if err != nil { 95 return fmt.Errorf("Error creating RDS Event Subscription %s: %s", name, err) 96 } 97 98 log.Println( 99 "[INFO] Waiting for RDS Event Subscription to be ready") 100 101 stateConf := &resource.StateChangeConf{ 102 Pending: []string{"creating"}, 103 Target: []string{"active"}, 104 Refresh: resourceAwsDbEventSubscriptionRefreshFunc(d, meta.(*AWSClient).rdsconn), 105 Timeout: 40 * time.Minute, 106 MinTimeout: 10 * time.Second, 107 Delay: 30 * time.Second, // Wait 30 secs before starting 108 } 109 110 // Wait, catching any errors 111 _, err = stateConf.WaitForState() 112 if err != nil { 113 return fmt.Errorf("Creating RDS Event Subscription %s failed: %s", d.Id(), err) 114 } 115 116 return resourceAwsDbEventSubscriptionRead(d, meta) 117 } 118 119 func resourceAwsDbEventSubscriptionRead(d *schema.ResourceData, meta interface{}) error { 120 sub, err := resourceAwsDbEventSubscriptionRetrieve(d.Get("name").(string), meta.(*AWSClient).rdsconn) 121 if err != nil { 122 return fmt.Errorf("Error retrieving RDS Event Subscription %s: %s", d.Id(), err) 123 } 124 if sub == nil { 125 d.SetId("") 126 return nil 127 } 128 129 d.SetId(*sub.CustSubscriptionId) 130 if err := d.Set("name", sub.CustSubscriptionId); err != nil { 131 return err 132 } 133 if err := d.Set("sns_topic", sub.SnsTopicArn); err != nil { 134 return err 135 } 136 if err := d.Set("source_type", sub.SourceType); err != nil { 137 return err 138 } 139 if err := d.Set("enabled", sub.Enabled); err != nil { 140 return err 141 } 142 if err := d.Set("source_ids", flattenStringList(sub.SourceIdsList)); err != nil { 143 return err 144 } 145 if err := d.Set("event_categories", flattenStringList(sub.EventCategoriesList)); err != nil { 146 return err 147 } 148 if err := d.Set("customer_aws_id", sub.CustomerAwsId); err != nil { 149 return err 150 } 151 152 // list tags for resource 153 // set tags 154 conn := meta.(*AWSClient).rdsconn 155 arn := buildRDSEventSubscriptionARN(d.Get("customer_aws_id").(string), d.Id(), meta.(*AWSClient).region) 156 resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{ 157 ResourceName: aws.String(arn), 158 }) 159 160 if err != nil { 161 log.Printf("[DEBUG] Error retrieving tags for ARN: %s", arn) 162 } 163 164 var dt []*rds.Tag 165 if len(resp.TagList) > 0 { 166 dt = resp.TagList 167 } 168 d.Set("tags", tagsToMapRDS(dt)) 169 170 return nil 171 } 172 173 func resourceAwsDbEventSubscriptionRetrieve( 174 name string, rdsconn *rds.RDS) (*rds.EventSubscription, error) { 175 176 request := &rds.DescribeEventSubscriptionsInput{ 177 SubscriptionName: aws.String(name), 178 } 179 180 describeResp, err := rdsconn.DescribeEventSubscriptions(request) 181 if err != nil { 182 if rdserr, ok := err.(awserr.Error); ok && rdserr.Code() == "SubscriptionNotFound" { 183 log.Printf("[WARN] No RDS Event Subscription by name (%s) found", name) 184 return nil, nil 185 } 186 return nil, fmt.Errorf("Error reading RDS Event Subscription %s: %s", name, err) 187 } 188 189 if len(describeResp.EventSubscriptionsList) != 1 { 190 return nil, fmt.Errorf("Unable to find RDS Event Subscription: %#v", describeResp.EventSubscriptionsList) 191 } 192 193 return describeResp.EventSubscriptionsList[0], nil 194 } 195 196 func resourceAwsDbEventSubscriptionUpdate(d *schema.ResourceData, meta interface{}) error { 197 rdsconn := meta.(*AWSClient).rdsconn 198 199 d.Partial(true) 200 requestUpdate := false 201 202 req := &rds.ModifyEventSubscriptionInput{ 203 SubscriptionName: aws.String(d.Id()), 204 } 205 206 if d.HasChange("event_categories") { 207 eventCategoriesSet := d.Get("event_categories").(*schema.Set) 208 req.EventCategories = make([]*string, eventCategoriesSet.Len()) 209 for i, eventCategory := range eventCategoriesSet.List() { 210 req.EventCategories[i] = aws.String(eventCategory.(string)) 211 } 212 requestUpdate = true 213 } 214 215 if d.HasChange("enabled") { 216 req.Enabled = aws.Bool(d.Get("enabled").(bool)) 217 requestUpdate = true 218 } 219 220 if d.HasChange("sns_topic") { 221 req.SnsTopicArn = aws.String(d.Get("sns_topic").(string)) 222 requestUpdate = true 223 } 224 225 if d.HasChange("source_type") { 226 req.SourceType = aws.String(d.Get("source_type").(string)) 227 requestUpdate = true 228 } 229 230 log.Printf("[DEBUG] Send RDS Event Subscription modification request: %#v", requestUpdate) 231 if requestUpdate { 232 log.Printf("[DEBUG] RDS Event Subscription modification request: %#v", req) 233 _, err := rdsconn.ModifyEventSubscription(req) 234 if err != nil { 235 return fmt.Errorf("Modifying RDS Event Subscription %s failed: %s", d.Id(), err) 236 } 237 238 log.Println( 239 "[INFO] Waiting for RDS Event Subscription modification to finish") 240 241 stateConf := &resource.StateChangeConf{ 242 Pending: []string{"modifying"}, 243 Target: []string{"active"}, 244 Refresh: resourceAwsDbEventSubscriptionRefreshFunc(d, meta.(*AWSClient).rdsconn), 245 Timeout: 40 * time.Minute, 246 MinTimeout: 10 * time.Second, 247 Delay: 30 * time.Second, // Wait 30 secs before starting 248 } 249 250 // Wait, catching any errors 251 _, err = stateConf.WaitForState() 252 if err != nil { 253 return fmt.Errorf("Modifying RDS Event Subscription %s failed: %s", d.Id(), err) 254 } 255 d.SetPartial("event_categories") 256 d.SetPartial("enabled") 257 d.SetPartial("sns_topic") 258 d.SetPartial("source_type") 259 } 260 261 arn := buildRDSEventSubscriptionARN(d.Get("customer_aws_id").(string), d.Id(), meta.(*AWSClient).region) 262 if err := setTagsRDS(rdsconn, d, arn); err != nil { 263 return err 264 } else { 265 d.SetPartial("tags") 266 } 267 268 if d.HasChange("source_ids") { 269 o, n := d.GetChange("source_ids") 270 if o == nil { 271 o = new(schema.Set) 272 } 273 if n == nil { 274 n = new(schema.Set) 275 } 276 277 os := o.(*schema.Set) 278 ns := n.(*schema.Set) 279 remove := expandStringList(os.Difference(ns).List()) 280 add := expandStringList(ns.Difference(os).List()) 281 282 if len(remove) > 0 { 283 for _, removing := range remove { 284 log.Printf("[INFO] Removing %s as a Source Identifier from %q", *removing, d.Id()) 285 _, err := rdsconn.RemoveSourceIdentifierFromSubscription(&rds.RemoveSourceIdentifierFromSubscriptionInput{ 286 SourceIdentifier: removing, 287 SubscriptionName: aws.String(d.Id()), 288 }) 289 if err != nil { 290 return err 291 } 292 } 293 } 294 295 if len(add) > 0 { 296 for _, adding := range add { 297 log.Printf("[INFO] Adding %s as a Source Identifier to %q", *adding, d.Id()) 298 _, err := rdsconn.AddSourceIdentifierToSubscription(&rds.AddSourceIdentifierToSubscriptionInput{ 299 SourceIdentifier: adding, 300 SubscriptionName: aws.String(d.Id()), 301 }) 302 if err != nil { 303 return err 304 } 305 } 306 } 307 d.SetPartial("source_ids") 308 } 309 310 d.Partial(false) 311 312 return nil 313 } 314 315 func resourceAwsDbEventSubscriptionDelete(d *schema.ResourceData, meta interface{}) error { 316 rdsconn := meta.(*AWSClient).rdsconn 317 deleteOpts := rds.DeleteEventSubscriptionInput{ 318 SubscriptionName: aws.String(d.Id()), 319 } 320 321 if _, err := rdsconn.DeleteEventSubscription(&deleteOpts); err != nil { 322 rdserr, ok := err.(awserr.Error) 323 if !ok { 324 return fmt.Errorf("Error deleting RDS Event Subscription %s: %s", d.Id(), err) 325 } 326 327 if rdserr.Code() != "DBEventSubscriptionNotFoundFault" { 328 log.Printf("[WARN] RDS Event Subscription %s missing during delete", d.Id()) 329 return fmt.Errorf("Error deleting RDS Event Subscription %s: %s", d.Id(), err) 330 } 331 } 332 333 stateConf := &resource.StateChangeConf{ 334 Pending: []string{"deleting"}, 335 Target: []string{}, 336 Refresh: resourceAwsDbEventSubscriptionRefreshFunc(d, meta.(*AWSClient).rdsconn), 337 Timeout: 40 * time.Minute, 338 MinTimeout: 10 * time.Second, 339 Delay: 30 * time.Second, // Wait 30 secs before starting 340 } 341 _, err := stateConf.WaitForState() 342 if err != nil { 343 return fmt.Errorf("Error deleting RDS Event Subscription %s: %s", d.Id(), err) 344 } 345 return err 346 } 347 348 func resourceAwsDbEventSubscriptionRefreshFunc( 349 d *schema.ResourceData, 350 rdsconn *rds.RDS) resource.StateRefreshFunc { 351 352 return func() (interface{}, string, error) { 353 sub, err := resourceAwsDbEventSubscriptionRetrieve(d.Get("name").(string), rdsconn) 354 355 if err != nil { 356 log.Printf("Error on retrieving DB Event Subscription when waiting: %s", err) 357 return nil, "", err 358 } 359 360 if sub == nil { 361 return nil, "", nil 362 } 363 364 if sub.Status != nil { 365 log.Printf("[DEBUG] DB Event Subscription status for %s: %s", d.Id(), *sub.Status) 366 } 367 368 return sub, *sub.Status, nil 369 } 370 } 371 372 func buildRDSEventSubscriptionARN(customerAwsId, subscriptionId, region string) string { 373 arn := fmt.Sprintf("arn:aws:rds:%s:%s:es:%s", region, customerAwsId, subscriptionId) 374 return arn 375 }