github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/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 }