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