github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/cloudfront_distribution_configuration_structure.go (about) 1 // CloudFront DistributionConfig structure helpers. 2 // 3 // These functions assist in pulling in data from Terraform resource 4 // configuration for the aws_cloudfront_distribution resource, as there are 5 // several sub-fields that require their own data type, and do not necessarily 6 // 1-1 translate to resource configuration. 7 8 package aws 9 10 import ( 11 "bytes" 12 "fmt" 13 "reflect" 14 "sort" 15 "strconv" 16 "time" 17 18 "github.com/aws/aws-sdk-go/aws" 19 "github.com/aws/aws-sdk-go/service/cloudfront" 20 "github.com/hashicorp/terraform/flatmap" 21 "github.com/hashicorp/terraform/helper/hashcode" 22 "github.com/hashicorp/terraform/helper/schema" 23 ) 24 25 // cloudFrontRoute53ZoneID defines the route 53 zone ID for CloudFront. This 26 // is used to set the zone_id attribute. 27 const cloudFrontRoute53ZoneID = "Z2FDTNDATAQYW2" 28 29 // Define Sort interface for []*string so we can ensure the order of 30 // geo_restrictions.locations 31 type StringPtrSlice []*string 32 33 func (p StringPtrSlice) Len() int { return len(p) } 34 func (p StringPtrSlice) Less(i, j int) bool { return *p[i] < *p[j] } 35 func (p StringPtrSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 36 37 // Assemble the *cloudfront.DistributionConfig variable. Calls out to various 38 // expander functions to convert attributes and sub-attributes to the various 39 // complex structures which are necessary to properly build the 40 // DistributionConfig structure. 41 // 42 // Used by the aws_cloudfront_distribution Create and Update functions. 43 func expandDistributionConfig(d *schema.ResourceData) *cloudfront.DistributionConfig { 44 distributionConfig := &cloudfront.DistributionConfig{ 45 CacheBehaviors: expandCacheBehaviors(d.Get("cache_behavior").(*schema.Set)), 46 CustomErrorResponses: expandCustomErrorResponses(d.Get("custom_error_response").(*schema.Set)), 47 DefaultCacheBehavior: expandDefaultCacheBehavior(d.Get("default_cache_behavior").(*schema.Set).List()[0].(map[string]interface{})), 48 Enabled: aws.Bool(d.Get("enabled").(bool)), 49 IsIPV6Enabled: aws.Bool(d.Get("is_ipv6_enabled").(bool)), 50 HttpVersion: aws.String(d.Get("http_version").(string)), 51 Origins: expandOrigins(d.Get("origin").(*schema.Set)), 52 PriceClass: aws.String(d.Get("price_class").(string)), 53 } 54 // This sets CallerReference if it's still pending computation (ie: new resource) 55 if v, ok := d.GetOk("caller_reference"); ok == false { 56 distributionConfig.CallerReference = aws.String(time.Now().Format(time.RFC3339Nano)) 57 } else { 58 distributionConfig.CallerReference = aws.String(v.(string)) 59 } 60 if v, ok := d.GetOk("comment"); ok { 61 distributionConfig.Comment = aws.String(v.(string)) 62 } else { 63 distributionConfig.Comment = aws.String("") 64 } 65 if v, ok := d.GetOk("default_root_object"); ok { 66 distributionConfig.DefaultRootObject = aws.String(v.(string)) 67 } else { 68 distributionConfig.DefaultRootObject = aws.String("") 69 } 70 if v, ok := d.GetOk("logging_config"); ok { 71 distributionConfig.Logging = expandLoggingConfig(v.(*schema.Set).List()[0].(map[string]interface{})) 72 } else { 73 distributionConfig.Logging = expandLoggingConfig(nil) 74 } 75 if v, ok := d.GetOk("aliases"); ok { 76 distributionConfig.Aliases = expandAliases(v.(*schema.Set)) 77 } else { 78 distributionConfig.Aliases = expandAliases(schema.NewSet(aliasesHash, []interface{}{})) 79 } 80 if v, ok := d.GetOk("restrictions"); ok { 81 distributionConfig.Restrictions = expandRestrictions(v.(*schema.Set).List()[0].(map[string]interface{})) 82 } 83 if v, ok := d.GetOk("viewer_certificate"); ok { 84 distributionConfig.ViewerCertificate = expandViewerCertificate(v.(*schema.Set).List()[0].(map[string]interface{})) 85 } 86 if v, ok := d.GetOk("web_acl_id"); ok { 87 distributionConfig.WebACLId = aws.String(v.(string)) 88 } else { 89 distributionConfig.WebACLId = aws.String("") 90 } 91 92 return distributionConfig 93 } 94 95 // Unpack the *cloudfront.DistributionConfig variable and set resource data. 96 // Calls out to flatten functions to convert the DistributionConfig 97 // sub-structures to their respective attributes in the 98 // aws_cloudfront_distribution resource. 99 // 100 // Used by the aws_cloudfront_distribution Read function. 101 func flattenDistributionConfig(d *schema.ResourceData, distributionConfig *cloudfront.DistributionConfig) error { 102 var err error 103 104 d.Set("enabled", distributionConfig.Enabled) 105 d.Set("is_ipv6_enabled", distributionConfig.IsIPV6Enabled) 106 d.Set("price_class", distributionConfig.PriceClass) 107 d.Set("hosted_zone_id", cloudFrontRoute53ZoneID) 108 109 err = d.Set("default_cache_behavior", flattenDefaultCacheBehavior(distributionConfig.DefaultCacheBehavior)) 110 if err != nil { 111 return err 112 } 113 err = d.Set("viewer_certificate", flattenViewerCertificate(distributionConfig.ViewerCertificate)) 114 if err != nil { 115 return err 116 } 117 118 if distributionConfig.CallerReference != nil { 119 d.Set("caller_reference", distributionConfig.CallerReference) 120 } 121 if distributionConfig.Comment != nil { 122 if *distributionConfig.Comment != "" { 123 d.Set("comment", distributionConfig.Comment) 124 } 125 } 126 if distributionConfig.DefaultRootObject != nil { 127 d.Set("default_root_object", distributionConfig.DefaultRootObject) 128 } 129 if distributionConfig.HttpVersion != nil { 130 d.Set("http_version", distributionConfig.HttpVersion) 131 } 132 if distributionConfig.WebACLId != nil { 133 d.Set("web_acl_id", distributionConfig.WebACLId) 134 } 135 136 if distributionConfig.CustomErrorResponses != nil { 137 err = d.Set("custom_error_response", flattenCustomErrorResponses(distributionConfig.CustomErrorResponses)) 138 if err != nil { 139 return err 140 } 141 } 142 if distributionConfig.CacheBehaviors != nil { 143 err = d.Set("cache_behavior", flattenCacheBehaviors(distributionConfig.CacheBehaviors)) 144 if err != nil { 145 return err 146 } 147 } 148 149 if distributionConfig.Logging != nil && *distributionConfig.Logging.Enabled { 150 err = d.Set("logging_config", flattenLoggingConfig(distributionConfig.Logging)) 151 } else { 152 err = d.Set("logging_config", schema.NewSet(loggingConfigHash, []interface{}{})) 153 } 154 if err != nil { 155 return err 156 } 157 158 if distributionConfig.Aliases != nil { 159 err = d.Set("aliases", flattenAliases(distributionConfig.Aliases)) 160 if err != nil { 161 return err 162 } 163 } 164 if distributionConfig.Restrictions != nil { 165 err = d.Set("restrictions", flattenRestrictions(distributionConfig.Restrictions)) 166 if err != nil { 167 return err 168 } 169 } 170 if *distributionConfig.Origins.Quantity > 0 { 171 err = d.Set("origin", flattenOrigins(distributionConfig.Origins)) 172 if err != nil { 173 return err 174 } 175 } 176 177 return nil 178 } 179 180 func expandDefaultCacheBehavior(m map[string]interface{}) *cloudfront.DefaultCacheBehavior { 181 cb := expandCacheBehavior(m) 182 var dcb cloudfront.DefaultCacheBehavior 183 184 simpleCopyStruct(cb, &dcb) 185 return &dcb 186 } 187 188 func flattenDefaultCacheBehavior(dcb *cloudfront.DefaultCacheBehavior) *schema.Set { 189 m := make(map[string]interface{}) 190 var cb cloudfront.CacheBehavior 191 192 simpleCopyStruct(dcb, &cb) 193 m = flattenCacheBehavior(&cb) 194 return schema.NewSet(defaultCacheBehaviorHash, []interface{}{m}) 195 } 196 197 // Assemble the hash for the aws_cloudfront_distribution default_cache_behavior 198 // TypeSet attribute. 199 func defaultCacheBehaviorHash(v interface{}) int { 200 var buf bytes.Buffer 201 m := v.(map[string]interface{}) 202 buf.WriteString(fmt.Sprintf("%t-", m["compress"].(bool))) 203 buf.WriteString(fmt.Sprintf("%s-", m["viewer_protocol_policy"].(string))) 204 buf.WriteString(fmt.Sprintf("%s-", m["target_origin_id"].(string))) 205 buf.WriteString(fmt.Sprintf("%d-", forwardedValuesHash(m["forwarded_values"].(*schema.Set).List()[0].(map[string]interface{})))) 206 buf.WriteString(fmt.Sprintf("%d-", m["min_ttl"].(int))) 207 if d, ok := m["trusted_signers"]; ok { 208 for _, e := range sortInterfaceSlice(d.([]interface{})) { 209 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 210 } 211 } 212 if d, ok := m["max_ttl"]; ok { 213 buf.WriteString(fmt.Sprintf("%d-", d.(int))) 214 } 215 if d, ok := m["smooth_streaming"]; ok { 216 buf.WriteString(fmt.Sprintf("%t-", d.(bool))) 217 } 218 if d, ok := m["default_ttl"]; ok { 219 buf.WriteString(fmt.Sprintf("%d-", d.(int))) 220 } 221 if d, ok := m["allowed_methods"]; ok { 222 for _, e := range sortInterfaceSlice(d.([]interface{})) { 223 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 224 } 225 } 226 if d, ok := m["cached_methods"]; ok { 227 for _, e := range sortInterfaceSlice(d.([]interface{})) { 228 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 229 } 230 } 231 if d, ok := m["lambda_function_association"]; ok { 232 var associations []interface{} 233 switch d.(type) { 234 case *schema.Set: 235 associations = d.(*schema.Set).List() 236 default: 237 associations = d.([]interface{}) 238 } 239 for _, lfa := range associations { 240 buf.WriteString(fmt.Sprintf("%d-", lambdaFunctionAssociationHash(lfa.(map[string]interface{})))) 241 } 242 } 243 return hashcode.String(buf.String()) 244 } 245 246 func expandCacheBehaviors(s *schema.Set) *cloudfront.CacheBehaviors { 247 var qty int64 248 var items []*cloudfront.CacheBehavior 249 for _, v := range s.List() { 250 items = append(items, expandCacheBehavior(v.(map[string]interface{}))) 251 qty++ 252 } 253 return &cloudfront.CacheBehaviors{ 254 Quantity: aws.Int64(qty), 255 Items: items, 256 } 257 } 258 259 func flattenCacheBehaviors(cbs *cloudfront.CacheBehaviors) *schema.Set { 260 s := []interface{}{} 261 for _, v := range cbs.Items { 262 s = append(s, flattenCacheBehavior(v)) 263 } 264 return schema.NewSet(cacheBehaviorHash, s) 265 } 266 267 func expandCacheBehavior(m map[string]interface{}) *cloudfront.CacheBehavior { 268 cb := &cloudfront.CacheBehavior{ 269 Compress: aws.Bool(m["compress"].(bool)), 270 ViewerProtocolPolicy: aws.String(m["viewer_protocol_policy"].(string)), 271 TargetOriginId: aws.String(m["target_origin_id"].(string)), 272 ForwardedValues: expandForwardedValues(m["forwarded_values"].(*schema.Set).List()[0].(map[string]interface{})), 273 MinTTL: aws.Int64(int64(m["min_ttl"].(int))), 274 MaxTTL: aws.Int64(int64(m["max_ttl"].(int))), 275 DefaultTTL: aws.Int64(int64(m["default_ttl"].(int))), 276 } 277 if v, ok := m["trusted_signers"]; ok { 278 cb.TrustedSigners = expandTrustedSigners(v.([]interface{})) 279 } else { 280 cb.TrustedSigners = expandTrustedSigners([]interface{}{}) 281 } 282 283 if v, ok := m["lambda_function_association"]; ok { 284 cb.LambdaFunctionAssociations = expandLambdaFunctionAssociations(v.(*schema.Set).List()) 285 } 286 287 if v, ok := m["smooth_streaming"]; ok { 288 cb.SmoothStreaming = aws.Bool(v.(bool)) 289 } 290 if v, ok := m["allowed_methods"]; ok { 291 cb.AllowedMethods = expandAllowedMethods(v.([]interface{})) 292 } 293 if v, ok := m["cached_methods"]; ok { 294 cb.AllowedMethods.CachedMethods = expandCachedMethods(v.([]interface{})) 295 } 296 if v, ok := m["path_pattern"]; ok { 297 cb.PathPattern = aws.String(v.(string)) 298 } 299 return cb 300 } 301 302 func flattenCacheBehavior(cb *cloudfront.CacheBehavior) map[string]interface{} { 303 m := make(map[string]interface{}) 304 305 m["compress"] = *cb.Compress 306 m["viewer_protocol_policy"] = *cb.ViewerProtocolPolicy 307 m["target_origin_id"] = *cb.TargetOriginId 308 m["forwarded_values"] = schema.NewSet(forwardedValuesHash, []interface{}{flattenForwardedValues(cb.ForwardedValues)}) 309 m["min_ttl"] = int(*cb.MinTTL) 310 311 if len(cb.TrustedSigners.Items) > 0 { 312 m["trusted_signers"] = flattenTrustedSigners(cb.TrustedSigners) 313 } 314 if len(cb.LambdaFunctionAssociations.Items) > 0 { 315 m["lambda_function_association"] = flattenLambdaFunctionAssociations(cb.LambdaFunctionAssociations) 316 } 317 if cb.MaxTTL != nil { 318 m["max_ttl"] = int(*cb.MaxTTL) 319 } 320 if cb.SmoothStreaming != nil { 321 m["smooth_streaming"] = *cb.SmoothStreaming 322 } 323 if cb.DefaultTTL != nil { 324 m["default_ttl"] = int(*cb.DefaultTTL) 325 } 326 if cb.AllowedMethods != nil { 327 m["allowed_methods"] = flattenAllowedMethods(cb.AllowedMethods) 328 } 329 if cb.AllowedMethods.CachedMethods != nil { 330 m["cached_methods"] = flattenCachedMethods(cb.AllowedMethods.CachedMethods) 331 } 332 if cb.PathPattern != nil { 333 m["path_pattern"] = *cb.PathPattern 334 } 335 return m 336 } 337 338 // Assemble the hash for the aws_cloudfront_distribution cache_behavior 339 // TypeSet attribute. 340 func cacheBehaviorHash(v interface{}) int { 341 var buf bytes.Buffer 342 m := v.(map[string]interface{}) 343 buf.WriteString(fmt.Sprintf("%t-", m["compress"].(bool))) 344 buf.WriteString(fmt.Sprintf("%s-", m["viewer_protocol_policy"].(string))) 345 buf.WriteString(fmt.Sprintf("%s-", m["target_origin_id"].(string))) 346 buf.WriteString(fmt.Sprintf("%d-", forwardedValuesHash(m["forwarded_values"].(*schema.Set).List()[0].(map[string]interface{})))) 347 buf.WriteString(fmt.Sprintf("%d-", m["min_ttl"].(int))) 348 if d, ok := m["trusted_signers"]; ok { 349 for _, e := range sortInterfaceSlice(d.([]interface{})) { 350 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 351 } 352 } 353 if d, ok := m["max_ttl"]; ok { 354 buf.WriteString(fmt.Sprintf("%d-", d.(int))) 355 } 356 if d, ok := m["smooth_streaming"]; ok { 357 buf.WriteString(fmt.Sprintf("%t-", d.(bool))) 358 } 359 if d, ok := m["default_ttl"]; ok { 360 buf.WriteString(fmt.Sprintf("%d-", d.(int))) 361 } 362 if d, ok := m["allowed_methods"]; ok { 363 for _, e := range sortInterfaceSlice(d.([]interface{})) { 364 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 365 } 366 } 367 if d, ok := m["cached_methods"]; ok { 368 for _, e := range sortInterfaceSlice(d.([]interface{})) { 369 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 370 } 371 } 372 if d, ok := m["path_pattern"]; ok { 373 buf.WriteString(fmt.Sprintf("%s-", d)) 374 } 375 if d, ok := m["lambda_function_association"]; ok { 376 var associations []interface{} 377 switch d.(type) { 378 case *schema.Set: 379 associations = d.(*schema.Set).List() 380 default: 381 associations = d.([]interface{}) 382 } 383 for _, lfa := range associations { 384 buf.WriteString(fmt.Sprintf("%d-", lambdaFunctionAssociationHash(lfa.(map[string]interface{})))) 385 } 386 } 387 return hashcode.String(buf.String()) 388 } 389 390 func expandTrustedSigners(s []interface{}) *cloudfront.TrustedSigners { 391 var ts cloudfront.TrustedSigners 392 if len(s) > 0 { 393 ts.Quantity = aws.Int64(int64(len(s))) 394 ts.Items = expandStringList(s) 395 ts.Enabled = aws.Bool(true) 396 } else { 397 ts.Quantity = aws.Int64(0) 398 ts.Enabled = aws.Bool(false) 399 } 400 return &ts 401 } 402 403 func flattenTrustedSigners(ts *cloudfront.TrustedSigners) []interface{} { 404 if ts.Items != nil { 405 return flattenStringList(ts.Items) 406 } 407 return []interface{}{} 408 } 409 410 func lambdaFunctionAssociationHash(v interface{}) int { 411 var buf bytes.Buffer 412 m := v.(map[string]interface{}) 413 buf.WriteString(fmt.Sprintf("%s-", m["event_type"].(string))) 414 buf.WriteString(fmt.Sprintf("%s", m["lambda_arn"].(string))) 415 return hashcode.String(buf.String()) 416 } 417 418 func expandLambdaFunctionAssociations(v interface{}) *cloudfront.LambdaFunctionAssociations { 419 if v == nil { 420 return &cloudfront.LambdaFunctionAssociations{ 421 Quantity: aws.Int64(0), 422 } 423 } 424 425 s := v.([]interface{}) 426 var lfa cloudfront.LambdaFunctionAssociations 427 lfa.Quantity = aws.Int64(int64(len(s))) 428 lfa.Items = make([]*cloudfront.LambdaFunctionAssociation, len(s)) 429 for i, lf := range s { 430 lfa.Items[i] = expandLambdaFunctionAssociation(lf.(map[string]interface{})) 431 } 432 return &lfa 433 } 434 435 func expandLambdaFunctionAssociation(lf map[string]interface{}) *cloudfront.LambdaFunctionAssociation { 436 var lfa cloudfront.LambdaFunctionAssociation 437 if v, ok := lf["event_type"]; ok { 438 lfa.EventType = aws.String(v.(string)) 439 } 440 if v, ok := lf["lambda_arn"]; ok { 441 lfa.LambdaFunctionARN = aws.String(v.(string)) 442 } 443 return &lfa 444 } 445 446 func flattenLambdaFunctionAssociations(lfa *cloudfront.LambdaFunctionAssociations) []interface{} { 447 s := make([]interface{}, len(lfa.Items)) 448 for i, v := range lfa.Items { 449 s[i] = flattenLambdaFunctionAssociation(v) 450 } 451 return s 452 } 453 454 func flattenLambdaFunctionAssociation(lfa *cloudfront.LambdaFunctionAssociation) map[string]interface{} { 455 m := map[string]interface{}{} 456 if lfa != nil { 457 m["event_type"] = *lfa.EventType 458 m["lambda_arn"] = *lfa.LambdaFunctionARN 459 } 460 return m 461 } 462 463 func expandForwardedValues(m map[string]interface{}) *cloudfront.ForwardedValues { 464 fv := &cloudfront.ForwardedValues{ 465 QueryString: aws.Bool(m["query_string"].(bool)), 466 } 467 if v, ok := m["cookies"]; ok && v.(*schema.Set).Len() > 0 { 468 fv.Cookies = expandCookiePreference(v.(*schema.Set).List()[0].(map[string]interface{})) 469 } 470 if v, ok := m["headers"]; ok { 471 fv.Headers = expandHeaders(v.([]interface{})) 472 } 473 if v, ok := m["query_string_cache_keys"]; ok { 474 fv.QueryStringCacheKeys = expandQueryStringCacheKeys(v.([]interface{})) 475 } 476 return fv 477 } 478 479 func flattenForwardedValues(fv *cloudfront.ForwardedValues) map[string]interface{} { 480 m := make(map[string]interface{}) 481 m["query_string"] = *fv.QueryString 482 if fv.Cookies != nil { 483 m["cookies"] = schema.NewSet(cookiePreferenceHash, []interface{}{flattenCookiePreference(fv.Cookies)}) 484 } 485 if fv.Headers != nil { 486 m["headers"] = flattenHeaders(fv.Headers) 487 } 488 if fv.QueryStringCacheKeys != nil { 489 m["query_string_cache_keys"] = flattenQueryStringCacheKeys(fv.QueryStringCacheKeys) 490 } 491 return m 492 } 493 494 // Assemble the hash for the aws_cloudfront_distribution forwarded_values 495 // TypeSet attribute. 496 func forwardedValuesHash(v interface{}) int { 497 var buf bytes.Buffer 498 m := v.(map[string]interface{}) 499 buf.WriteString(fmt.Sprintf("%t-", m["query_string"].(bool))) 500 if d, ok := m["cookies"]; ok && d.(*schema.Set).Len() > 0 { 501 buf.WriteString(fmt.Sprintf("%d-", cookiePreferenceHash(d.(*schema.Set).List()[0].(map[string]interface{})))) 502 } 503 if d, ok := m["headers"]; ok { 504 for _, e := range sortInterfaceSlice(d.([]interface{})) { 505 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 506 } 507 } 508 if d, ok := m["query_string_cache_keys"]; ok { 509 for _, e := range sortInterfaceSlice(d.([]interface{})) { 510 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 511 } 512 } 513 return hashcode.String(buf.String()) 514 } 515 516 func expandHeaders(d []interface{}) *cloudfront.Headers { 517 return &cloudfront.Headers{ 518 Quantity: aws.Int64(int64(len(d))), 519 Items: expandStringList(d), 520 } 521 } 522 523 func flattenHeaders(h *cloudfront.Headers) []interface{} { 524 if h.Items != nil { 525 return flattenStringList(h.Items) 526 } 527 return []interface{}{} 528 } 529 530 func expandQueryStringCacheKeys(d []interface{}) *cloudfront.QueryStringCacheKeys { 531 return &cloudfront.QueryStringCacheKeys{ 532 Quantity: aws.Int64(int64(len(d))), 533 Items: expandStringList(d), 534 } 535 } 536 537 func flattenQueryStringCacheKeys(k *cloudfront.QueryStringCacheKeys) []interface{} { 538 if k.Items != nil { 539 return flattenStringList(k.Items) 540 } 541 return []interface{}{} 542 } 543 544 func expandCookiePreference(m map[string]interface{}) *cloudfront.CookiePreference { 545 cp := &cloudfront.CookiePreference{ 546 Forward: aws.String(m["forward"].(string)), 547 } 548 if v, ok := m["whitelisted_names"]; ok { 549 cp.WhitelistedNames = expandCookieNames(v.([]interface{})) 550 } 551 return cp 552 } 553 554 func flattenCookiePreference(cp *cloudfront.CookiePreference) map[string]interface{} { 555 m := make(map[string]interface{}) 556 m["forward"] = *cp.Forward 557 if cp.WhitelistedNames != nil { 558 m["whitelisted_names"] = flattenCookieNames(cp.WhitelistedNames) 559 } 560 return m 561 } 562 563 // Assemble the hash for the aws_cloudfront_distribution cookies 564 // TypeSet attribute. 565 func cookiePreferenceHash(v interface{}) int { 566 var buf bytes.Buffer 567 m := v.(map[string]interface{}) 568 buf.WriteString(fmt.Sprintf("%s-", m["forward"].(string))) 569 if d, ok := m["whitelisted_names"]; ok { 570 for _, e := range sortInterfaceSlice(d.([]interface{})) { 571 buf.WriteString(fmt.Sprintf("%s-", e.(string))) 572 } 573 } 574 return hashcode.String(buf.String()) 575 } 576 577 func expandCookieNames(d []interface{}) *cloudfront.CookieNames { 578 return &cloudfront.CookieNames{ 579 Quantity: aws.Int64(int64(len(d))), 580 Items: expandStringList(d), 581 } 582 } 583 584 func flattenCookieNames(cn *cloudfront.CookieNames) []interface{} { 585 if cn.Items != nil { 586 return flattenStringList(cn.Items) 587 } 588 return []interface{}{} 589 } 590 591 func expandAllowedMethods(s []interface{}) *cloudfront.AllowedMethods { 592 return &cloudfront.AllowedMethods{ 593 Quantity: aws.Int64(int64(len(s))), 594 Items: expandStringList(s), 595 } 596 } 597 598 func flattenAllowedMethods(am *cloudfront.AllowedMethods) []interface{} { 599 if am.Items != nil { 600 return flattenStringList(am.Items) 601 } 602 return []interface{}{} 603 } 604 605 func expandCachedMethods(s []interface{}) *cloudfront.CachedMethods { 606 return &cloudfront.CachedMethods{ 607 Quantity: aws.Int64(int64(len(s))), 608 Items: expandStringList(s), 609 } 610 } 611 612 func flattenCachedMethods(cm *cloudfront.CachedMethods) []interface{} { 613 if cm.Items != nil { 614 return flattenStringList(cm.Items) 615 } 616 return []interface{}{} 617 } 618 619 func expandOrigins(s *schema.Set) *cloudfront.Origins { 620 qty := 0 621 items := []*cloudfront.Origin{} 622 for _, v := range s.List() { 623 items = append(items, expandOrigin(v.(map[string]interface{}))) 624 qty++ 625 } 626 return &cloudfront.Origins{ 627 Quantity: aws.Int64(int64(qty)), 628 Items: items, 629 } 630 } 631 632 func flattenOrigins(ors *cloudfront.Origins) *schema.Set { 633 s := []interface{}{} 634 for _, v := range ors.Items { 635 s = append(s, flattenOrigin(v)) 636 } 637 return schema.NewSet(originHash, s) 638 } 639 640 func expandOrigin(m map[string]interface{}) *cloudfront.Origin { 641 origin := &cloudfront.Origin{ 642 Id: aws.String(m["origin_id"].(string)), 643 DomainName: aws.String(m["domain_name"].(string)), 644 } 645 if v, ok := m["custom_header"]; ok { 646 origin.CustomHeaders = expandCustomHeaders(v.(*schema.Set)) 647 } 648 if v, ok := m["custom_origin_config"]; ok { 649 if s := v.(*schema.Set).List(); len(s) > 0 { 650 origin.CustomOriginConfig = expandCustomOriginConfig(s[0].(map[string]interface{})) 651 } 652 } 653 if v, ok := m["origin_path"]; ok { 654 origin.OriginPath = aws.String(v.(string)) 655 } 656 if v, ok := m["s3_origin_config"]; ok { 657 if s := v.(*schema.Set).List(); len(s) > 0 { 658 origin.S3OriginConfig = expandS3OriginConfig(s[0].(map[string]interface{})) 659 } 660 } 661 662 // if both custom and s3 origin are missing, add an empty s3 origin 663 // One or the other must be specified, but the S3 origin can be "empty" 664 if origin.S3OriginConfig == nil && origin.CustomOriginConfig == nil { 665 origin.S3OriginConfig = &cloudfront.S3OriginConfig{ 666 OriginAccessIdentity: aws.String(""), 667 } 668 } 669 670 return origin 671 } 672 673 func flattenOrigin(or *cloudfront.Origin) map[string]interface{} { 674 m := make(map[string]interface{}) 675 m["origin_id"] = *or.Id 676 m["domain_name"] = *or.DomainName 677 if or.CustomHeaders != nil { 678 m["custom_header"] = flattenCustomHeaders(or.CustomHeaders) 679 } 680 if or.CustomOriginConfig != nil { 681 m["custom_origin_config"] = schema.NewSet(customOriginConfigHash, []interface{}{flattenCustomOriginConfig(or.CustomOriginConfig)}) 682 } 683 if or.OriginPath != nil { 684 m["origin_path"] = *or.OriginPath 685 } 686 if or.S3OriginConfig != nil { 687 if or.S3OriginConfig.OriginAccessIdentity != nil && *or.S3OriginConfig.OriginAccessIdentity != "" { 688 m["s3_origin_config"] = schema.NewSet(s3OriginConfigHash, []interface{}{flattenS3OriginConfig(or.S3OriginConfig)}) 689 } 690 } 691 return m 692 } 693 694 // Assemble the hash for the aws_cloudfront_distribution origin 695 // TypeSet attribute. 696 func originHash(v interface{}) int { 697 var buf bytes.Buffer 698 m := v.(map[string]interface{}) 699 buf.WriteString(fmt.Sprintf("%s-", m["origin_id"].(string))) 700 buf.WriteString(fmt.Sprintf("%s-", m["domain_name"].(string))) 701 if v, ok := m["custom_header"]; ok { 702 buf.WriteString(fmt.Sprintf("%d-", customHeadersHash(v.(*schema.Set)))) 703 } 704 if v, ok := m["custom_origin_config"]; ok { 705 if s := v.(*schema.Set).List(); len(s) > 0 { 706 buf.WriteString(fmt.Sprintf("%d-", customOriginConfigHash((s[0].(map[string]interface{}))))) 707 } 708 } 709 if v, ok := m["origin_path"]; ok { 710 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 711 } 712 if v, ok := m["s3_origin_config"]; ok { 713 if s := v.(*schema.Set).List(); len(s) > 0 { 714 buf.WriteString(fmt.Sprintf("%d-", s3OriginConfigHash((s[0].(map[string]interface{}))))) 715 } 716 } 717 return hashcode.String(buf.String()) 718 } 719 720 func expandCustomHeaders(s *schema.Set) *cloudfront.CustomHeaders { 721 qty := 0 722 items := []*cloudfront.OriginCustomHeader{} 723 for _, v := range s.List() { 724 items = append(items, expandOriginCustomHeader(v.(map[string]interface{}))) 725 qty++ 726 } 727 return &cloudfront.CustomHeaders{ 728 Quantity: aws.Int64(int64(qty)), 729 Items: items, 730 } 731 } 732 733 func flattenCustomHeaders(chs *cloudfront.CustomHeaders) *schema.Set { 734 s := []interface{}{} 735 for _, v := range chs.Items { 736 s = append(s, flattenOriginCustomHeader(v)) 737 } 738 return schema.NewSet(originCustomHeaderHash, s) 739 } 740 741 func expandOriginCustomHeader(m map[string]interface{}) *cloudfront.OriginCustomHeader { 742 return &cloudfront.OriginCustomHeader{ 743 HeaderName: aws.String(m["name"].(string)), 744 HeaderValue: aws.String(m["value"].(string)), 745 } 746 } 747 748 func flattenOriginCustomHeader(och *cloudfront.OriginCustomHeader) map[string]interface{} { 749 return map[string]interface{}{ 750 "name": *och.HeaderName, 751 "value": *och.HeaderValue, 752 } 753 } 754 755 // Helper function used by originHash to get a composite hash for all 756 // aws_cloudfront_distribution custom_header attributes. 757 func customHeadersHash(s *schema.Set) int { 758 var buf bytes.Buffer 759 for _, v := range s.List() { 760 buf.WriteString(fmt.Sprintf("%d-", originCustomHeaderHash(v))) 761 } 762 return hashcode.String(buf.String()) 763 } 764 765 // Assemble the hash for the aws_cloudfront_distribution custom_header 766 // TypeSet attribute. 767 func originCustomHeaderHash(v interface{}) int { 768 var buf bytes.Buffer 769 m := v.(map[string]interface{}) 770 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 771 buf.WriteString(fmt.Sprintf("%s-", m["value"].(string))) 772 return hashcode.String(buf.String()) 773 } 774 775 func expandCustomOriginConfig(m map[string]interface{}) *cloudfront.CustomOriginConfig { 776 return &cloudfront.CustomOriginConfig{ 777 OriginProtocolPolicy: aws.String(m["origin_protocol_policy"].(string)), 778 HTTPPort: aws.Int64(int64(m["http_port"].(int))), 779 HTTPSPort: aws.Int64(int64(m["https_port"].(int))), 780 OriginSslProtocols: expandCustomOriginConfigSSL(m["origin_ssl_protocols"].([]interface{})), 781 } 782 } 783 784 func flattenCustomOriginConfig(cor *cloudfront.CustomOriginConfig) map[string]interface{} { 785 return map[string]interface{}{ 786 "origin_protocol_policy": *cor.OriginProtocolPolicy, 787 "http_port": int(*cor.HTTPPort), 788 "https_port": int(*cor.HTTPSPort), 789 "origin_ssl_protocols": flattenCustomOriginConfigSSL(cor.OriginSslProtocols), 790 } 791 } 792 793 // Assemble the hash for the aws_cloudfront_distribution custom_origin_config 794 // TypeSet attribute. 795 func customOriginConfigHash(v interface{}) int { 796 var buf bytes.Buffer 797 m := v.(map[string]interface{}) 798 buf.WriteString(fmt.Sprintf("%s-", m["origin_protocol_policy"].(string))) 799 buf.WriteString(fmt.Sprintf("%d-", m["http_port"].(int))) 800 buf.WriteString(fmt.Sprintf("%d-", m["https_port"].(int))) 801 for _, v := range sortInterfaceSlice(m["origin_ssl_protocols"].([]interface{})) { 802 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 803 } 804 return hashcode.String(buf.String()) 805 } 806 807 func expandCustomOriginConfigSSL(s []interface{}) *cloudfront.OriginSslProtocols { 808 items := expandStringList(s) 809 return &cloudfront.OriginSslProtocols{ 810 Quantity: aws.Int64(int64(len(items))), 811 Items: items, 812 } 813 } 814 815 func flattenCustomOriginConfigSSL(osp *cloudfront.OriginSslProtocols) []interface{} { 816 return flattenStringList(osp.Items) 817 } 818 819 func expandS3OriginConfig(m map[string]interface{}) *cloudfront.S3OriginConfig { 820 return &cloudfront.S3OriginConfig{ 821 OriginAccessIdentity: aws.String(m["origin_access_identity"].(string)), 822 } 823 } 824 825 func flattenS3OriginConfig(s3o *cloudfront.S3OriginConfig) map[string]interface{} { 826 return map[string]interface{}{ 827 "origin_access_identity": *s3o.OriginAccessIdentity, 828 } 829 } 830 831 // Assemble the hash for the aws_cloudfront_distribution s3_origin_config 832 // TypeSet attribute. 833 func s3OriginConfigHash(v interface{}) int { 834 var buf bytes.Buffer 835 m := v.(map[string]interface{}) 836 buf.WriteString(fmt.Sprintf("%s-", m["origin_access_identity"].(string))) 837 return hashcode.String(buf.String()) 838 } 839 840 func expandCustomErrorResponses(s *schema.Set) *cloudfront.CustomErrorResponses { 841 qty := 0 842 items := []*cloudfront.CustomErrorResponse{} 843 for _, v := range s.List() { 844 items = append(items, expandCustomErrorResponse(v.(map[string]interface{}))) 845 qty++ 846 } 847 return &cloudfront.CustomErrorResponses{ 848 Quantity: aws.Int64(int64(qty)), 849 Items: items, 850 } 851 } 852 853 func flattenCustomErrorResponses(ers *cloudfront.CustomErrorResponses) *schema.Set { 854 s := []interface{}{} 855 for _, v := range ers.Items { 856 s = append(s, flattenCustomErrorResponse(v)) 857 } 858 return schema.NewSet(customErrorResponseHash, s) 859 } 860 861 func expandCustomErrorResponse(m map[string]interface{}) *cloudfront.CustomErrorResponse { 862 er := cloudfront.CustomErrorResponse{ 863 ErrorCode: aws.Int64(int64(m["error_code"].(int))), 864 } 865 if v, ok := m["error_caching_min_ttl"]; ok { 866 er.ErrorCachingMinTTL = aws.Int64(int64(v.(int))) 867 } 868 if v, ok := m["response_code"]; ok && v.(int) != 0 { 869 er.ResponseCode = aws.String(strconv.Itoa(v.(int))) 870 } else { 871 er.ResponseCode = aws.String("") 872 } 873 if v, ok := m["response_page_path"]; ok { 874 er.ResponsePagePath = aws.String(v.(string)) 875 } 876 877 return &er 878 } 879 880 func flattenCustomErrorResponse(er *cloudfront.CustomErrorResponse) map[string]interface{} { 881 m := make(map[string]interface{}) 882 m["error_code"] = int(*er.ErrorCode) 883 if er.ErrorCachingMinTTL != nil { 884 m["error_caching_min_ttl"] = int(*er.ErrorCachingMinTTL) 885 } 886 if er.ResponseCode != nil { 887 m["response_code"], _ = strconv.Atoi(*er.ResponseCode) 888 } 889 if er.ResponsePagePath != nil { 890 m["response_page_path"] = *er.ResponsePagePath 891 } 892 return m 893 } 894 895 // Assemble the hash for the aws_cloudfront_distribution custom_error_response 896 // TypeSet attribute. 897 func customErrorResponseHash(v interface{}) int { 898 var buf bytes.Buffer 899 m := v.(map[string]interface{}) 900 buf.WriteString(fmt.Sprintf("%d-", m["error_code"].(int))) 901 if v, ok := m["error_caching_min_ttl"]; ok { 902 buf.WriteString(fmt.Sprintf("%d-", v.(int))) 903 } 904 if v, ok := m["response_code"]; ok { 905 buf.WriteString(fmt.Sprintf("%d-", v.(int))) 906 } 907 if v, ok := m["response_page_path"]; ok { 908 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 909 } 910 return hashcode.String(buf.String()) 911 } 912 913 func expandLoggingConfig(m map[string]interface{}) *cloudfront.LoggingConfig { 914 var lc cloudfront.LoggingConfig 915 if m != nil { 916 lc.Prefix = aws.String(m["prefix"].(string)) 917 lc.Bucket = aws.String(m["bucket"].(string)) 918 lc.IncludeCookies = aws.Bool(m["include_cookies"].(bool)) 919 lc.Enabled = aws.Bool(true) 920 } else { 921 lc.Prefix = aws.String("") 922 lc.Bucket = aws.String("") 923 lc.IncludeCookies = aws.Bool(false) 924 lc.Enabled = aws.Bool(false) 925 } 926 return &lc 927 } 928 929 func flattenLoggingConfig(lc *cloudfront.LoggingConfig) *schema.Set { 930 m := make(map[string]interface{}) 931 m["prefix"] = *lc.Prefix 932 m["bucket"] = *lc.Bucket 933 m["include_cookies"] = *lc.IncludeCookies 934 return schema.NewSet(loggingConfigHash, []interface{}{m}) 935 } 936 937 // Assemble the hash for the aws_cloudfront_distribution logging_config 938 // TypeSet attribute. 939 func loggingConfigHash(v interface{}) int { 940 var buf bytes.Buffer 941 m := v.(map[string]interface{}) 942 buf.WriteString(fmt.Sprintf("%s-", m["prefix"].(string))) 943 buf.WriteString(fmt.Sprintf("%s-", m["bucket"].(string))) 944 buf.WriteString(fmt.Sprintf("%t-", m["include_cookies"].(bool))) 945 return hashcode.String(buf.String()) 946 } 947 948 func expandAliases(as *schema.Set) *cloudfront.Aliases { 949 s := as.List() 950 var aliases cloudfront.Aliases 951 if len(s) > 0 { 952 aliases.Quantity = aws.Int64(int64(len(s))) 953 aliases.Items = expandStringList(s) 954 } else { 955 aliases.Quantity = aws.Int64(0) 956 } 957 return &aliases 958 } 959 960 func flattenAliases(aliases *cloudfront.Aliases) *schema.Set { 961 if aliases.Items != nil { 962 return schema.NewSet(aliasesHash, flattenStringList(aliases.Items)) 963 } 964 return schema.NewSet(aliasesHash, []interface{}{}) 965 } 966 967 // Assemble the hash for the aws_cloudfront_distribution aliases 968 // TypeSet attribute. 969 func aliasesHash(v interface{}) int { 970 return hashcode.String(v.(string)) 971 } 972 973 func expandRestrictions(m map[string]interface{}) *cloudfront.Restrictions { 974 return &cloudfront.Restrictions{ 975 GeoRestriction: expandGeoRestriction(m["geo_restriction"].(*schema.Set).List()[0].(map[string]interface{})), 976 } 977 } 978 979 func flattenRestrictions(r *cloudfront.Restrictions) *schema.Set { 980 m := make(map[string]interface{}) 981 s := schema.NewSet(geoRestrictionHash, []interface{}{flattenGeoRestriction(r.GeoRestriction)}) 982 m["geo_restriction"] = s 983 return schema.NewSet(restrictionsHash, []interface{}{m}) 984 } 985 986 // Assemble the hash for the aws_cloudfront_distribution restrictions 987 // TypeSet attribute. 988 func restrictionsHash(v interface{}) int { 989 var buf bytes.Buffer 990 m := v.(map[string]interface{}) 991 buf.WriteString(fmt.Sprintf("%d-", geoRestrictionHash(m["geo_restriction"].(*schema.Set).List()[0].(map[string]interface{})))) 992 return hashcode.String(buf.String()) 993 } 994 995 func expandGeoRestriction(m map[string]interface{}) *cloudfront.GeoRestriction { 996 gr := cloudfront.GeoRestriction{ 997 RestrictionType: aws.String(m["restriction_type"].(string)), 998 } 999 if v, ok := m["locations"]; ok { 1000 gr.Quantity = aws.Int64(int64(len(v.([]interface{})))) 1001 gr.Items = expandStringList(v.([]interface{})) 1002 sort.Sort(StringPtrSlice(gr.Items)) 1003 } else { 1004 gr.Quantity = aws.Int64(0) 1005 } 1006 return &gr 1007 } 1008 1009 func flattenGeoRestriction(gr *cloudfront.GeoRestriction) map[string]interface{} { 1010 m := make(map[string]interface{}) 1011 1012 m["restriction_type"] = *gr.RestrictionType 1013 if gr.Items != nil { 1014 sort.Sort(StringPtrSlice(gr.Items)) 1015 m["locations"] = flattenStringList(gr.Items) 1016 } 1017 return m 1018 } 1019 1020 // Assemble the hash for the aws_cloudfront_distribution geo_restriction 1021 // TypeSet attribute. 1022 func geoRestrictionHash(v interface{}) int { 1023 var buf bytes.Buffer 1024 m := v.(map[string]interface{}) 1025 // All keys added in alphabetical order. 1026 buf.WriteString(fmt.Sprintf("%s-", m["restriction_type"].(string))) 1027 if v, ok := m["locations"]; ok { 1028 for _, w := range sortInterfaceSlice(v.([]interface{})) { 1029 buf.WriteString(fmt.Sprintf("%s-", w.(string))) 1030 } 1031 } 1032 return hashcode.String(buf.String()) 1033 } 1034 1035 func expandViewerCertificate(m map[string]interface{}) *cloudfront.ViewerCertificate { 1036 var vc cloudfront.ViewerCertificate 1037 if v, ok := m["iam_certificate_id"]; ok && v != "" { 1038 vc.IAMCertificateId = aws.String(v.(string)) 1039 vc.SSLSupportMethod = aws.String(m["ssl_support_method"].(string)) 1040 } else if v, ok := m["acm_certificate_arn"]; ok && v != "" { 1041 vc.ACMCertificateArn = aws.String(v.(string)) 1042 vc.SSLSupportMethod = aws.String(m["ssl_support_method"].(string)) 1043 } else { 1044 vc.CloudFrontDefaultCertificate = aws.Bool(m["cloudfront_default_certificate"].(bool)) 1045 } 1046 if v, ok := m["minimum_protocol_version"]; ok && v != "" { 1047 vc.MinimumProtocolVersion = aws.String(v.(string)) 1048 } 1049 return &vc 1050 } 1051 1052 func flattenViewerCertificate(vc *cloudfront.ViewerCertificate) *schema.Set { 1053 m := make(map[string]interface{}) 1054 1055 if vc.IAMCertificateId != nil { 1056 m["iam_certificate_id"] = *vc.IAMCertificateId 1057 m["ssl_support_method"] = *vc.SSLSupportMethod 1058 } 1059 if vc.ACMCertificateArn != nil { 1060 m["acm_certificate_arn"] = *vc.ACMCertificateArn 1061 m["ssl_support_method"] = *vc.SSLSupportMethod 1062 } 1063 if vc.CloudFrontDefaultCertificate != nil { 1064 m["cloudfront_default_certificate"] = *vc.CloudFrontDefaultCertificate 1065 } 1066 if vc.MinimumProtocolVersion != nil { 1067 m["minimum_protocol_version"] = *vc.MinimumProtocolVersion 1068 } 1069 return schema.NewSet(viewerCertificateHash, []interface{}{m}) 1070 } 1071 1072 // Assemble the hash for the aws_cloudfront_distribution viewer_certificate 1073 // TypeSet attribute. 1074 func viewerCertificateHash(v interface{}) int { 1075 var buf bytes.Buffer 1076 m := v.(map[string]interface{}) 1077 if v, ok := m["iam_certificate_id"]; ok && v.(string) != "" { 1078 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 1079 buf.WriteString(fmt.Sprintf("%s-", m["ssl_support_method"].(string))) 1080 } else if v, ok := m["acm_certificate_arn"]; ok && v.(string) != "" { 1081 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 1082 buf.WriteString(fmt.Sprintf("%s-", m["ssl_support_method"].(string))) 1083 } else { 1084 buf.WriteString(fmt.Sprintf("%t-", m["cloudfront_default_certificate"].(bool))) 1085 } 1086 if v, ok := m["minimum_protocol_version"]; ok && v.(string) != "" { 1087 buf.WriteString(fmt.Sprintf("%s-", v.(string))) 1088 } 1089 return hashcode.String(buf.String()) 1090 } 1091 1092 // Do a top-level copy of struct fields from one struct to another. Used to 1093 // copy fields between CacheBehavior and DefaultCacheBehavior structs. 1094 func simpleCopyStruct(src, dst interface{}) { 1095 s := reflect.ValueOf(src).Elem() 1096 d := reflect.ValueOf(dst).Elem() 1097 1098 for i := 0; i < s.NumField(); i++ { 1099 if s.Field(i).CanSet() == true { 1100 if s.Field(i).Interface() != nil { 1101 for j := 0; j < d.NumField(); j++ { 1102 if d.Type().Field(j).Name == s.Type().Field(i).Name { 1103 d.Field(j).Set(s.Field(i)) 1104 } 1105 } 1106 } 1107 } 1108 } 1109 } 1110 1111 // Convert *cloudfront.ActiveTrustedSigners to a flatmap.Map type, which ensures 1112 // it can probably be inserted into the schema.TypeMap type used by the 1113 // active_trusted_signers attribute. 1114 func flattenActiveTrustedSigners(ats *cloudfront.ActiveTrustedSigners) flatmap.Map { 1115 m := make(map[string]interface{}) 1116 s := []interface{}{} 1117 m["enabled"] = *ats.Enabled 1118 1119 for _, v := range ats.Items { 1120 signer := make(map[string]interface{}) 1121 signer["aws_account_number"] = *v.AwsAccountNumber 1122 signer["key_pair_ids"] = aws.StringValueSlice(v.KeyPairIds.Items) 1123 s = append(s, signer) 1124 } 1125 m["items"] = s 1126 return flatmap.Flatten(m) 1127 }