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