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