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