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