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  }