github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/aws/resource_aws_wafregional_byte_match_set.go (about)

     1  package aws
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/aws/aws-sdk-go/aws"
     7  	"github.com/aws/aws-sdk-go/aws/awserr"
     8  	"github.com/aws/aws-sdk-go/service/waf"
     9  	"github.com/aws/aws-sdk-go/service/wafregional"
    10  	"github.com/hashicorp/errwrap"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceAwsWafRegionalByteMatchSet() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAwsWafRegionalByteMatchSetCreate,
    17  		Read:   resourceAwsWafRegionalByteMatchSetRead,
    18  		Update: resourceAwsWafRegionalByteMatchSetUpdate,
    19  		Delete: resourceAwsWafRegionalByteMatchSetDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  			"byte_match_tuple": &schema.Schema{
    28  				Type:     schema.TypeSet,
    29  				Optional: true,
    30  				Elem: &schema.Resource{
    31  					Schema: map[string]*schema.Schema{
    32  						"field_to_match": {
    33  							Type:     schema.TypeSet,
    34  							Required: true,
    35  							MaxItems: 1,
    36  							Elem: &schema.Resource{
    37  								Schema: map[string]*schema.Schema{
    38  									"data": {
    39  										Type:     schema.TypeString,
    40  										Optional: true,
    41  									},
    42  									"type": {
    43  										Type:     schema.TypeString,
    44  										Required: true,
    45  									},
    46  								},
    47  							},
    48  						},
    49  						"positional_constraint": &schema.Schema{
    50  							Type:     schema.TypeString,
    51  							Required: true,
    52  						},
    53  						"target_string": &schema.Schema{
    54  							Type:     schema.TypeString,
    55  							Optional: true,
    56  						},
    57  						"text_transformation": &schema.Schema{
    58  							Type:     schema.TypeString,
    59  							Required: true,
    60  						},
    61  					},
    62  				},
    63  			},
    64  		},
    65  	}
    66  }
    67  
    68  func resourceAwsWafRegionalByteMatchSetCreate(d *schema.ResourceData, meta interface{}) error {
    69  	conn := meta.(*AWSClient).wafregionalconn
    70  	region := meta.(*AWSClient).region
    71  
    72  	log.Printf("[INFO] Creating ByteMatchSet: %s", d.Get("name").(string))
    73  
    74  	wr := newWafRegionalRetryer(conn, region)
    75  	out, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
    76  		params := &waf.CreateByteMatchSetInput{
    77  			ChangeToken: token,
    78  			Name:        aws.String(d.Get("name").(string)),
    79  		}
    80  		return conn.CreateByteMatchSet(params)
    81  	})
    82  
    83  	if err != nil {
    84  		return errwrap.Wrapf("[ERROR] Error creating ByteMatchSet: {{err}}", err)
    85  	}
    86  	resp := out.(*waf.CreateByteMatchSetOutput)
    87  
    88  	d.SetId(*resp.ByteMatchSet.ByteMatchSetId)
    89  
    90  	return resourceAwsWafRegionalByteMatchSetUpdate(d, meta)
    91  }
    92  
    93  func resourceAwsWafRegionalByteMatchSetRead(d *schema.ResourceData, meta interface{}) error {
    94  	conn := meta.(*AWSClient).wafregionalconn
    95  
    96  	log.Printf("[INFO] Reading ByteMatchSet: %s", d.Get("name").(string))
    97  
    98  	params := &waf.GetByteMatchSetInput{
    99  		ByteMatchSetId: aws.String(d.Id()),
   100  	}
   101  
   102  	resp, err := conn.GetByteMatchSet(params)
   103  	if err != nil {
   104  		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" {
   105  			log.Printf("[WARN] WAF IPSet (%s) not found, error code (404)", d.Id())
   106  			d.SetId("")
   107  			return nil
   108  		}
   109  
   110  		return err
   111  	}
   112  
   113  	d.Set("byte_match_tuple", flattenWafByteMatchTuplesWR(resp.ByteMatchSet.ByteMatchTuples))
   114  	d.Set("name", resp.ByteMatchSet.Name)
   115  
   116  	return nil
   117  }
   118  
   119  func flattenWafByteMatchTuplesWR(in []*waf.ByteMatchTuple) []interface{} {
   120  	tuples := make([]interface{}, len(in), len(in))
   121  
   122  	for i, tuple := range in {
   123  		field_to_match := tuple.FieldToMatch
   124  		m := map[string]interface{}{
   125  			"type": *field_to_match.Type,
   126  		}
   127  
   128  		if field_to_match.Data == nil {
   129  			m["data"] = ""
   130  		} else {
   131  			m["data"] = *field_to_match.Data
   132  		}
   133  
   134  		var ms []map[string]interface{}
   135  		ms = append(ms, m)
   136  
   137  		tuple := map[string]interface{}{
   138  			"field_to_match":        ms,
   139  			"positional_constraint": *tuple.PositionalConstraint,
   140  			"target_string":         tuple.TargetString,
   141  			"text_transformation":   *tuple.TextTransformation,
   142  		}
   143  		tuples[i] = tuple
   144  	}
   145  
   146  	return tuples
   147  }
   148  
   149  func resourceAwsWafRegionalByteMatchSetUpdate(d *schema.ResourceData, meta interface{}) error {
   150  	conn := meta.(*AWSClient).wafregionalconn
   151  	region := meta.(*AWSClient).region
   152  	log.Printf("[INFO] Updating ByteMatchSet: %s", d.Get("name").(string))
   153  
   154  	if d.HasChange("byte_match_tuple") {
   155  		o, n := d.GetChange("byte_match_tuple")
   156  		oldT, newT := o.(*schema.Set).List(), n.(*schema.Set).List()
   157  
   158  		err := updateByteMatchSetResourceWR(d, oldT, newT, conn, region)
   159  		if err != nil {
   160  			return errwrap.Wrapf("[ERROR] Error updating ByteMatchSet: {{err}}", err)
   161  		}
   162  	}
   163  	return resourceAwsWafRegionalByteMatchSetRead(d, meta)
   164  }
   165  
   166  func resourceAwsWafRegionalByteMatchSetDelete(d *schema.ResourceData, meta interface{}) error {
   167  	conn := meta.(*AWSClient).wafregionalconn
   168  	region := meta.(*AWSClient).region
   169  
   170  	log.Printf("[INFO] Deleting ByteMatchSet: %s", d.Get("name").(string))
   171  
   172  	oldT := d.Get("byte_match_tuple").(*schema.Set).List()
   173  
   174  	if len(oldT) > 0 {
   175  		var newT []interface{}
   176  
   177  		err := updateByteMatchSetResourceWR(d, oldT, newT, conn, region)
   178  		if err != nil {
   179  			return errwrap.Wrapf("[ERROR] Error deleting ByteMatchSet: {{err}}", err)
   180  		}
   181  	}
   182  
   183  	wr := newWafRegionalRetryer(conn, region)
   184  	_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
   185  		req := &waf.DeleteByteMatchSetInput{
   186  			ChangeToken:    token,
   187  			ByteMatchSetId: aws.String(d.Id()),
   188  		}
   189  		return conn.DeleteByteMatchSet(req)
   190  	})
   191  	if err != nil {
   192  		return errwrap.Wrapf("[ERROR] Error deleting ByteMatchSet: {{err}}", err)
   193  	}
   194  
   195  	return nil
   196  }
   197  
   198  func updateByteMatchSetResourceWR(d *schema.ResourceData, oldT, newT []interface{}, conn *wafregional.WAFRegional, region string) error {
   199  	wr := newWafRegionalRetryer(conn, region)
   200  	_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
   201  		req := &waf.UpdateByteMatchSetInput{
   202  			ChangeToken:    token,
   203  			ByteMatchSetId: aws.String(d.Id()),
   204  			Updates:        diffByteMatchSetTuple(oldT, newT),
   205  		}
   206  
   207  		return conn.UpdateByteMatchSet(req)
   208  	})
   209  	if err != nil {
   210  		return errwrap.Wrapf("[ERROR] Error updating ByteMatchSet: {{err}}", err)
   211  	}
   212  
   213  	return nil
   214  }
   215  
   216  func expandFieldToMatchWR(d map[string]interface{}) *waf.FieldToMatch {
   217  	return &waf.FieldToMatch{
   218  		Type: aws.String(d["type"].(string)),
   219  		Data: aws.String(d["data"].(string)),
   220  	}
   221  }
   222  
   223  func flattenFieldToMatchWR(fm *waf.FieldToMatch) map[string]interface{} {
   224  	m := make(map[string]interface{})
   225  	m["data"] = *fm.Data
   226  	m["type"] = *fm.Type
   227  	return m
   228  }
   229  
   230  func diffByteMatchSetTuple(oldT, newT []interface{}) []*waf.ByteMatchSetUpdate {
   231  	updates := make([]*waf.ByteMatchSetUpdate, 0)
   232  
   233  	for _, ot := range oldT {
   234  		tuple := ot.(map[string]interface{})
   235  
   236  		if idx, contains := sliceContainsMap(newT, tuple); contains {
   237  			newT = append(newT[:idx], newT[idx+1:]...)
   238  			continue
   239  		}
   240  
   241  		updates = append(updates, &waf.ByteMatchSetUpdate{
   242  			Action: aws.String(waf.ChangeActionDelete),
   243  			ByteMatchTuple: &waf.ByteMatchTuple{
   244  				FieldToMatch:         expandFieldToMatch(tuple["field_to_match"].(*schema.Set).List()[0].(map[string]interface{})),
   245  				PositionalConstraint: aws.String(tuple["positional_constraint"].(string)),
   246  				TargetString:         []byte(tuple["target_string"].(string)),
   247  				TextTransformation:   aws.String(tuple["text_transformation"].(string)),
   248  			},
   249  		})
   250  	}
   251  
   252  	for _, nt := range newT {
   253  		tuple := nt.(map[string]interface{})
   254  
   255  		updates = append(updates, &waf.ByteMatchSetUpdate{
   256  			Action: aws.String(waf.ChangeActionInsert),
   257  			ByteMatchTuple: &waf.ByteMatchTuple{
   258  				FieldToMatch:         expandFieldToMatch(tuple["field_to_match"].(*schema.Set).List()[0].(map[string]interface{})),
   259  				PositionalConstraint: aws.String(tuple["positional_constraint"].(string)),
   260  				TargetString:         []byte(tuple["target_string"].(string)),
   261  				TextTransformation:   aws.String(tuple["text_transformation"].(string)),
   262  			},
   263  		})
   264  	}
   265  	return updates
   266  }